+
    jHàjé? ã                   ó”  a€ ERÛ Et%0 t R t^ RIt^ RIt^ RIt^ RIt^ RIt^ RIt^ RIt^ RI	t	^ RI
t
^ RIt^ RIt^ RIt^ RIt^ RIt^ RIt^ RIt^ RIt^ RIHtHt ^ RIHtHt ^ RIHt ^ RIHt ^ RIHt ^ RI H!t! ^ RI"H#t#H$t% ]PL                  ! ]'4      t(R	 R
 lt)RRRRRRRRRRRRRR/t*]+! ]*4      t,]+! 0 ERÜm4      t-]+! 0 ERÝm4      t.]+! RR04      t/]+! RR04      t0R"R#R$^<R%R/R& R' llt1R(t2R)t3^t4]Pj                  ! ]44      t6R* R+ lt7]8]933R, lt:R-t;R.t<ERÞR/ R0 llt=R1 R2 lt>R3 R4 lt?R5 R6 lt@]+! 0 ERßm4      tAERÞR: R; lltBERàR= R> lltCR? R@ ltDRA RB ltERC RD ltFRE RF ltGRG RH ltHRItIRsJ] ^ k RJ RK ltKRL RM ltLRN RO lt$ERÞRPRRQR/RR RS llltMRT RU ltNRV RW ltORX RY ltPRZ R[ ltQR\ R] ltRERÞR^ R_ lltS^ RITtT^ R`ITHUtU ^ RaIVHWtW ^ RbIXHYtYHZtZH[t[H\t\H]t]H^t^H_t_H`t`Hata ]PÄ                  PÇ                  ^ ]d! ]W! ]e4      PÍ                  4       PÎ                  ^,          4      4       ^ RcIhHitiHjtj ^ RdIkHltl ^ ReImHntnHotoHptpHqtqHrtrHstsHttt ^ RfIuHvtvHwtwHxtxHyty ^ RgIzH{t{H|t|H}t} ^ RhI~Ht ^ RiI€H�t�H‚t‚ ^ RjIƒH„t„H…t… ^ RkI†H‡t‡ ^ RlIˆH‰t‰HŠtŠH‹t‹HŒtŒ ^ RmI�HŽtŽH�t� ]Y'       d   ^ RnI�H‘t‘ Rot’Rpt“Rq Rr lt”Rs t•]‹! RtRu4      t–ERát—Rv Rw lt˜RxRyRzR/R{ R| llt™R} R~ ltšR R€ lt›]›! R9R�RtRu4      w  tœt�R‚ Rƒ ltžR„ R… ltŸR† R‡ lt ERâRˆ R‰ llt¡ERâRŠ R‹ llt¢RŒ R� lt£ERãRŽ R� llt¤R� R‘ lt¥]‹! R’R“4      t¦]›! R7R”R’R“4      w  t§t¨ERäR• R– llt©ERäR— R˜ lltªERåR™ Rš llt«]‹! R›Rœ4      t¬]›! R8R�R›Rœ4      w  t­t®RRžRRŸRR RR¡RR¢/t¯ERæR£ R¤ llt°ERæR¥ R¦ llt±]‹! R§R¨4      t²]‹! R©Rª4      t³]›! R«R¬R§R¨4      w  t´tµ]›! R­R®R©Rª4      w  t¶t·R�]–R”]¦R�]¬R¬]²R®]³/t¸]Œ! 4       t¹]Š! 4       tºR¯t»R°t¼R±t½R²t¾R³R7R´RµR¶]Ž3t¿]–]¦]¬]²]³.R· ERç 4       OR¸ ]¿ 4       O5tÀR¹tÁERètÂERétÃRº R» ltÄR¼R½R¾R¿RÀRÁRÂRÃ]PÄ                  EP‹                  RÄRÅ4      RÆ]PÄ                  EP‹                  RÇRÈ4      ]PÄ                  EP‹                  RÇRÉ4      RÊRËRÌRÍ.]Ä! RÎ4      O]Ä! RÏ4      O5tÆRÐ RÑ ltÇRÒ RÓ ltÈRÔ RÕ ltÉRÖ R× ltÊRØ RÙ ltËRÚ RÛ ltÌRÜ RÝ ltÍRÞ Rß ltÎRà Rá ltÏRâ Rã ltÐRäR<RåR</Ræ Rç lltÑRè Ré ltÒRê Rë ltÓRì Rí ltÔERêRï Rð lltÕRñ Rò ltÖERêRó Rô llt×0 ERëmtØRõ Rö ltÙR÷ Rø ltÚRù Rú ltÛERêRû Rü lltÜRý Rþ ltÝERàRÿ ER  lltÞERêERR</ER ER llltßERêER ER lltà]
EPÂ                  ! ER4      tâER ER ltãERÞER	 ER
 lltäER ER ltå/ ERERbERERbERERbERERbERERbERERbERERbERERbERERbERERbERERbER ERbER!ER"bER#ER$bER%ER&bER'ER(bER)ER*bER+ER,ER-ER.ER/ERER0ERER1ER/Ctæ0 ERkERkER2kERkER3kERkERkER4kER5kERkERkERkERkERkER kER6kR¼kER7kER8kER9kER:kER;kER<kER=kER0kER>kER?kER@kERAkER/kERBkERCkER1kERDkEREkERFkERGkERHkERIkERJkERKkERLkERMkERNkEROkERPkERQkERRkERSkERTkERUkERVkERWkERXkERYkERZkER[kER\kER]kER^kER_kER`kERakERbkERckERdkERekERfkERgkERhkERikERjkERkkERlkERmkERnktçRERoRERoRERpR ERqR!ERr/tèERìté] ^k ERsEP‹                  ]ê! ERt ]é 4       ]ëERuERv7      4      tìERwtí]
EPÂ                  ! ERx]ì,           ERy,           ]í,           ERz,           ]
EPÜ                  4      tï]
EPÂ                  ! ER{]í,           ER|,           ]
EPÜ                  4      tðER} ER~ ltñER ER€ ltòER� ER‚ ltóERƒ ER„ ltôER…tõER† ER‡ ltöERˆ ER‰ lt÷ERŠ ER‹ ltøERŒ ER� ltùERŽ ER� ltú]
EPÂ                  ! ER�]
EPö                  4      tü]
EPÂ                  ! ER‘4      týER’ ER“ ltþER” ER• ltÿER– ER— lEt ER˜ ER™ lEtERš ER› lEtERœ ER� lEt]U ! ERž ERŸ4      4       Et]æ]¯]è3 U UUu/ uF&  p E]! V EP                  4       4       F  w  rW!bK	  	  K(  	  uppp Et] ^k ER  ER¡ lEtER¢RîER£RîER¤R/ER¥ ER¦ llEt	ER¢RîER£RîER¤R/ER§ ER¨ llEt
]U ! ER© ERª4      4       EtER« ER¬ lEt]U ! ER­ ER®4      4       Et]
EPÂ                  ! ER¯]
EPÜ                  4      ]
EPÂ                  ! ER°]
EPÜ                  4      ]
EPÂ                  ! ER±]
EPÜ                  4      3Et] ^k ER² ER³ lEt]U ! ER´ ERµ4      4       Et]U ! ER¶ ER·4      4       EtRIEt]+! 0 ERím4      EtERîEtERïEtERðER¾ ER¿ llEtERÀ ERÁ lEtER¸ERÂ 3ER¹ERÃ 3ERºERÄ 3ER»ERÅ 3ER¼ERÆ 3ER½ERÇ 33Et] ^k ERêERÈ ERÉ llEtERðERÊ ERË llEt ! ERÌ ERÍ]d4      EtERÎR</ERÏ ERÐ llEtERñEt]^]{.]_]\]a]dERÍ3,          ,          ,          3,          EtERÞERÑ ERÒ llEtERÞERÓ ERÔ llEt ERÕ ERÖ lEt!ER× ERØ lEt"E]Et# ! ERÙ ERÚ]4      Et$R# u uppp i (ò  zZBase platform adapter interface; every platform adapter inherits from BasePlatformAdapter.N)ÚABCÚabstractmethod)Úmake_user_dirÚunusable_dir_remedy)Úsafe_url_for_log)Únormalize_proxy_url)Út)Újittered_backoff)Úfirst_proxy_env_valueÚshould_bypass_proxyc                ó<   € V ^8„  d   QhR\         P                  RR/# )é   ÚtaskÚreturnN©ÚasyncioÚTask)Úformats   "Ú;/home/ubuntu/.hermes/hermes-agent/gateway/platforms/base.pyÚ__annotate__r       s"   € ÷ Xñ X¬g¯l©lð X¸tñ Xó    c                ó�   € V P                  4       '       d   R# V P                  4       pVe   \        P                  RWR7       R# R# )z¥Done-callback for a detached fatal-error handler task (carrier cancelled in
``_notify_fatal_error``): retrieve its exception so asyncio never logs "never retrieved".Nz,Detached fatal-error handler task failed: %s©Úexc_info)Ú	cancelledÚ	exceptionÚloggerÚerror)r   Úexcs   & r   Ú#_consume_detached_handler_exceptionr       s;   € ð ‡~�~×ÒÙØ
�.‰.Ó
€CØ
‚Ü�‰ÐCÀSˆÖWñ r   ú.oggz	audio/oggú.opusz
audio/opusú.mp3z
audio/mpegú.m2aú.wavz	audio/wavú.m4az	audio/m4aú.flacz
audio/flacú.mp4ú.movú.aviú.mkvú.webmú.jpgú.jpegú.pngú.webpú.gifÚbitrateÚ32kÚtimeoutÚoutput_pathc                óp   € V ^8„  d   QhR\         R\         R\        R\         R,          R\         R,          /# )r   Úpathr1   r3   r4   Nr   ©ÚstrÚint)r   s   "r   r   r   8   s9   € ÷ !ñ !¤ð !´ð !Äsð !Ü'*¨T¥zð!Ü=@À4½Zñ!r   c               ó8  € ^ RI pVP                  R4      pV'       g   R# Vf2   \        P                  ! RRR7      w  rg\        P
                  ! V4       MTp\        P                  P                  \        V 4      4      \        P                  P                  V4      8H  pV'       d
   VR,           MTp	 \        P                  ! VRRR	R
\        V 4      RRRRRVRRRRRRRRV	.RV\        P                  RR7      p
V
P                  ^ 8X  dE   \        P                  P                  V	4      ^ 8”  d!   V'       d   \        P                  ! W—4       V# \        P!                  RY
P                  V
P"                  ;'       g    RP%                  RRR7      R ,          4       \(        P*                  ! \,        4      ;_uu_ 4        \        P.                  ! V	4       RRR4       R#   \&         d    \        P!                  R!T RR"7        Lhi ; i  + '       g   i     R# ; i)#u{  Best-effort ffmpeg transcode to Ogg/Opus (voip-tuned) for native voice bubbles: the written
``.ogg`` path (a NEW temp file unless ``output_path`` is given; caller cleans up), or None when
ffmpeg is missing/fails. ``output_path`` may equal ``path`` (in-place container repair) â€” the
encode goes through a sidecar so a failed run never truncates the source. Blocking (to_thread).NÚffmpegÚvoice_transcode_r    )ÚprefixÚsuffixz.tmp.oggz-vr   z-yz-iz-acodecÚlibopusz-acÚ1z-b:az-vbrÚonz-applicationÚvoipz-compression_levelÚ10z-fÚoggTF)Úcapture_outputr3   ÚstdinÚcheckz:ffmpeg Ogg/Opus transcode of %s failed (returncode=%s): %sr   úutf-8Úreplace©Úerrors:Niô  Nz)voice transcode to Ogg/Opus failed for %sr   )ÚshutilÚwhichÚtempfileÚmkstempÚosÚcloser6   Úabspathr8   Ú
subprocessÚrunÚDEVNULLÚ
returncodeÚgetsizerI   r   ÚwarningÚstderrÚdecodeÚ	ExceptionÚ
contextlibÚsuppressÚOSErrorÚunlink)r6   r1   r3   r4   Ú_shutilr;   ÚfdÚogg_pathÚin_placeÚ	work_pathÚresults   &$$$       r   Útranscode_to_ogg_opusrf   8   s©  € ó Ø�]‰]˜8Ó$€FßÙØÒÜ×'Ò'Ð/AÈ&ÔQ‰ˆÜ
�Š��àˆÜ�w‰w�‰œs 4›yÓ)¬R¯W©W¯_©_¸XÓ-FÑF€Hß)1�˜:Ö%°x€IðYÜ—’Ø�T˜7 D¨$´°D³	Ø˜	 5¨#¨v°wÀÈØ˜VÐ%9¸4ÀÀuÈiðYð  ¨¼
×8JÑ8JÐRWô	Yˆð
 ×Ñ Ô!¤b§g¡g§o¡o°iÓ&@À1Ô&DßÜ—
’
˜9Ô/ØˆOÜ�‰ÐSÐUY×[lÑ[lØŸ™×,Ð,¨×4Ñ4°WÀYÐ4ÓOÐPTÕUô	Wô 
×	Ò	œW×	%Õ	%Ü
�	Š	�)Ô÷ 
&áøô	 ô YÜ�‰ÐBÀDÐSWˆÖXðYúç	%Ö	%áús1   Â3BG Ä7G Å-G Å=G Æ>HÇ#HÈHÈH	ç      >@ç      @c                ó$   € V ^8„  d   QhR\         /# ©r   r   ©r8   )r   s   "r   r   r   c   s   € ÷ $ñ $¤ñ $r   c                ób   € \        V RV 4      p\        T;'       g    R4      P                  4       # )z=Normalize a Platform enum / raw string into a lowercase name.ÚvalueÚ )Úgetattrr8   Úlower)Úplatformrm   s   & r   Ú_platform_namerr   c   s*   € ä�H˜g xÓ0€EÜˆu�{ˆ{˜Ó×!Ñ!Ó#Ð#r   c                ó0   €  V ! 4       #   T d    Tu # i ; i)zX``thunk()``, or ``default`` when it raises one of ``exc`` (numeric config/env coercion).© )ÚthunkÚdefaultr   s   &&&r   Ú_or_defaultrw   i   s"   € ðÙ‹wˆøØô ØŠðús   ‚	 ‰	”gffffffÖ?ç      ð?c                óL   € V ^8„  d   QhR\         R,          R\        R,          /# )r   Úreply_to_message_idNr   ©r8   Údict)r   s   "r   r   r   u   s%   € ÷ ñ ¼SÀ4½Zð ÔSWÐZ^ÕS^ñ r   c                ó
  € \        V RR4      p\        \        V RR4      4      pVe   RV/M/ pVR8X  d   \        V RR4      MRpV'       d   \        V4      VR&   V'       g   R# VR8X  d_   \        V RR4      R	8X  dM   R
VR&   \        V4      R9  d   \        V4      VR&   T;'       g    \        V RR4      pVe   \        V4      VR&   \        \        V RR4      ;'       g    R4      P                  4       pV'       d   WtR&   V# )zÔPlatform-aware thread metadata for adapter sends. Telegram DM topics route with
``message_thread_id`` + a reply anchor; anchorless synthetic/resumed sends fall back to
``direct_messages_topic_id`` when supported.Ú	thread_idNrq   ÚslackÚscope_idÚslack_team_idÚtelegramÚ	chat_typeÚdmTÚ telegram_dm_topic_reply_fallbackrn   Údirect_messages_topic_idÚ
message_idÚtelegram_reply_to_message_idÚprofileÚhermes_profile>   rn   r@   )ro   rr   r8   Ústrip)Úsourcerz   r~   rq   Úmetadatar€   Úanchorr‰   s   &&      r   Ú_thread_metadata_for_sourcer�   u   s  € ô ˜ ¨TÓ2€IÜœg f¨j¸$Ó?Ó@€HØ+4Ò+@�˜YÑ'Àb€Hð 5=ÀÔ4GŒw�v˜z¨4Ô0ÈT€HßÜ$'¨£Mˆ�Ñ!ßÙØ�:Ô¤'¨&°+¸tÓ"DÈÔ"LØ7;ˆÐ3Ñ4Üˆy‹> Ô*Ü36°y³>ˆHÐ/Ñ0Ø$×KÐK¬°¸ÀdÓ(KˆØÒÜ7:¸6³{ˆHÐ3Ñ4ô ”'˜& )¨TÓ2×8Ð8°bÓ9×?Ñ?ÓA€GßØ%,Ð!Ñ"Ø€Or   c                ó2   € V ^8„  d   QhR\         R,          /# ©r   r   N©r|   )r   s   "r   r   r   ’   s   € ÷ Uñ U¬°­ñ Ur   c                ó@   € \        V P                  \        V 4      4      # )zG``_thread_metadata_for_source`` for an event, anchored on its reply id.)r�   rŒ   Ú_reply_anchor_for_event©Úevents   &r   Ú_thread_metadata_for_eventr—   ’   s   € ä& u§|¡|Ô5LÈUÓ5SÓTÐTr   c                ó>   € V ^8„  d   QhR\         R,          R\         /# )r   r�   Nr   r’   )r   s   "r   r   r   —   s   € ÷ ñ ¤D¨4¥Kð ´Dñ r   c                ó:   € V '       d   \        V 4      M/ pRVR&   V# )z>Clone metadata and mark a user-visible reply as notify-worthy.TÚnotifyr’   )r�   Únotify_metadatas   & r   Ú_mark_notify_metadatarœ   —   s   € ç(0”d˜8”n°b€OØ $€O�HÑØÐr   c                ó2   € V ^8„  d   QhR\         R,          /# r‘   rk   )r   s   "r   r   r   ž   s   € ÷ .ñ .¤c¨D¥jñ .r   c                ó6  € \        V RR4      pVe   V# \        V RR4      p\        \        VRR4      4      p\        VRR4      p\        V RR4      p\        V RR4      '       g5   VR	8X  d0   \        V\        4      '       d   VP	                  R
4      '       d   R# VR8X  d?   V'       d7   \        VRR4      R8w  d   R# \        V RR4      ;'       g    \        V RR4      # VR8X  d)   V'       d!   \        V RR4      '       d   \        V RR4      # \        V RR4      # )z;Return reply_to id for platforms that need reply semantics.Úreply_anchor_overrideNrŒ   rq   r~   Úraw_messageÚinternalFr   Ú_hermes_no_thread_responser‚   rƒ   r„   r‡   rz   Úfeishu)ro   rr   Ú
isinstancer|   Úget)r–   ÚoverriderŒ   rq   r~   r    s   &     r   r”   r”   ž   s  € ä�uÐ5°tÓ<€HØÒØˆÜ�U˜H dÓ+€FÜœg f¨j¸$Ó?Ó@€HÜ˜ ¨TÓ2€IÜ˜% °Ó5€KÜˆu�j %×(Ò(¨X¸Ô-@ÄZÐP[Ô]a×EbÒEbØ1<·±ÐA]×1^Ò1^ñ Ø�:Ô§)ô �6˜;¨Ó-°Ô5ÙÜ�u˜l¨DÓ1×`Ð`´W¸UÐDYÐ[_Ó5`Ð`Ø�8Ô§	¬g°eÐ=RÐTX×.YÒ.YÜ�uÐ3°TÓ:Ð:Ü�5˜,¨Ó-Ð-r   ÚaudioÚvideoÚimagec                óJ   € V ^8„  d   QhR\         R\         R,          R\         /# )r   ÚkindÚ	file_nameNr   rk   )r   s   "r   r   r   º   s*   € ÷ Fñ Fœcð F¬c°D­jð FÄCñ Fr   c                ó|   € V \         9   d   \        RV  24      MT pV'       d   \        RW!R7      # \        RVR7      # )zQUser-facing "couldn't deliver" notice; ``file_name`` is the only name ever shown.zgateway.notify.media_kind.z.gateway.notify.media_delivery_failed_with_name)r«   r¬   z$gateway.notify.media_delivery_failed)r«   )Ú_MEDIA_KIND_KEYSr   )r«   r¬   Ú
kind_labels   && r   Ú_media_failure_textr°   º   s>   € à;?ÔCSÔ;S”Ð/°¨vÐ6Ô7ÐY]€JßÜÐAÈ
ÔhÐhÜÐ3¸*ÔEÐEr   Fc                ó<   € V ^8„  d   QhR\         R\        R\        /# )r   ÚextÚis_voicer   ©r8   Úbool)r   s   "r   r   r   Â   s&   € ÷ 
Iñ 
I¬cð 
I¼Tð 
IÌdñ 
Ir   c                óš   € T;'       g    RP                  4       pV\        9  d   R# \        V 4      R8w  d   R# T;'       g
    V\        9   # )uf  True when a media file should use the platform's audio sender. Telegram: explicit
``is_voice`` ([[audio_as_voice]]) routes ANY format to the voice sender (adapter transcodes
non-Opus); otherwise only sendAudio's MP3/M4A qualify â€” a plain Opus/OGG attachment is never
turned into a voice bubble, everything else â†’ document. Other platforms: any audio ext.rn   Fr‚   T)rp   Ú_AUDIO_EXTSrr   Ú_TELEGRAM_AUDIO_ATTACHMENT_EXTS)rq   r²   r³   Únormalized_exts   &&& r   Úshould_send_media_as_audiorº   Â   sG   € ð
 —i�i˜R×&Ñ&Ó(€NØœ[Ô(ÙÜ�hÓ :Ô-ÙØ×HÐH�~Ô)HÑHÐHr   c                ó$   € V ^8„  d   QhR\         /# rj   rk   )r   s   "r   r   r   Ï   s   € ÷ ñ ¬Cñ r   c                ó`  € ^ RI Hp \        V 4      V9   d   RMRp\        P                  P                  \        P                  ! 4       RR\        P                  ! 4       P                  R,           RV 24      p\        P                  ! \        P                  P                  V4      RR	7       V# )
uÎ  Unique temp output path for gateway auto-TTS: ``.ogg`` for ``OPUS_VOICE_PLATFORMS``
(the tool's ``_repair_ogg_container`` then guarantees real Opus bytes), else ``.mp3``.
Platform-awareness lives HERE because ``_clear_session_env`` wipes the TTS tool's
``HERMES_SESSION_PLATFORM`` contextvar before the post-handler auto-TTS block runs.

Platforms whose native voice bubbles require Ogg/Opus (``tools.tts_tool.OPUS_VOICE_PLATFORMS`` â€” the
single source of truth) get an explicit ``.ogg`` path; the tool's central container repair
(``_repair_ogg_container``) then guarantees real Ogg/Opus bytes for every provider, including MP3-only
backends like Edge TTS. Everything else keeps the MP3 default. See #36685, #57049.
)ÚOPUS_VOICE_PLATFORMSrD   Úmp3Úhermes_voiceÚ
tts_reply_ºNé   NÚ.T)Úexist_ok)Útools.tts_toolr½   rr   rP   r6   ÚjoinrN   Ú
gettempdirÚuuidÚuuid4ÚhexÚmakedirsÚdirname)rq   r½   r²   Ú
audio_paths   &   r   Úbuild_auto_tts_output_pathrÎ   Ï   s�   € õ 4Ü! (Ó+Ð/CÔC‰%È€CÜ—‘—‘Ü×ÒÓ˜~°¼D¿JºJ»L×<LÑ<LÈSÕ<QÐ;RÐRSÐTWÐSXÐ/Yó[€Jä‡K‚K”—‘—‘ 
Ó+°dÕ;ØÐr   c                ó0   € V ^8„  d   QhR\         R\        /# )r   Úsr   r7   )r   s   "r   r   r   â   s   € ÷ +ñ +”ð +œñ +r   c                óD   € \        V P                  R4      4      ^,          # )u  UTF-16 code units in *s* â€” Telegram's 4 096 limit counts those, so astral chars
(emoji, CJK Ext B) cost **two** units although Python's ``len()`` counts one.

Ported from nearai/ironclaw#2304 which discovered the same discrepancy in Rust's ``chars().count()``.
z	utf-16-le)ÚlenÚencode)rÐ   s   &r   Ú	utf16_lenrÔ   â   s   € ô ˆq�x‰x˜Ó$Ó%¨Õ*Ð*r   c                ó<   € V ^8„  d   QhR\         R\        R\        /# )r   rÐ   Úbudgetr   r7   )r   s   "r   r   r   ë   s!   € ÷ ñ œ#ð ¤sð ´sñ r   c                óÄ   € V! V 4      V8:  d   \        V 4      # ^ \        V 4      rCW48  d6   W4,           ^,           ^,          pV! V RV 4      V8:  d   TpK0  V^,
          pK;  V# )zNLargest codepoint offset *n* with ``len_fn(s[:n]) <= budget`` (binary search).N©rÒ   )rÐ   rÖ   Úlen_fnÚloÚhiÚmids   &&&   r   Ú_custom_unit_to_cprÝ   ë   s\   € áˆaƒy�FÔÜ�1‹vˆØ”�A“ˆØ
Œ'Ø�w˜�{˜qÕ ˆÙ�!�D�S�'‹?˜fÔ$ØŠBà�q•ŠBØ€Ir   c                ó<   € V ^8„  d   QhR\         R\        R\         /# )r   rÐ   Úlimitr   r7   )r   s   "r   r   r   ù   s!   € ÷ 7ñ 7¤#ð 7¬cð 7´cñ 7r   c                ó(   € V R\        W\        4       # )uT   Longest prefix of *s* with UTF-16 length â‰¤ *limit*; never splits a surrogate pair.N)rÝ   rÔ   )rÐ   rß   s   &&r   Ú_prefix_within_utf16_limitrá   ù   s   € àÐ5Ô  ¬9Ó5Ð6Ð6r   c                ó0   € V ^8„  d   QhR\         R\        /# )r   Úhostr   r´   )r   s   "r   r   r   þ   s   € ÷ ñ ¤ð ¬ñ r   c                ó>  € \         P                  ! \        4      ;_uu_ 4        \        P                  ! V 4      p\        VRR4      pVP                  ;'       g    T;'       d    VP                  '       * uuRRR4       #   + '       g   i     M; i \        P                  ! T R\        P                  \        P                  4      p\        ;QJ d    R T 4       F  '       g   K   R# 	  R# ! R T 4       4      #   \        P                  \        3 d     R# i ; i)z˜True if *host* would expose the server beyond loopback (incl. IPv4-mapped
::ffff:127.0.0.1); hostnames are resolved and DNS failure fails closed (True).Úipv4_mappedNc              3   ó~   "  € T F3  Ev r\         P                  ! V^ ,          4      P                  '       * x € K5  	  R# 5i©é    N)Ú	ipaddressÚ
ip_addressÚis_loopback)Ú.0Ú_Úsockaddrs   &  r   Ú	<genexpr>Ú(is_network_accessible.<locals>.<genexpr>	  s/   é € ÐbÑYaÉÈ!”y×+Ò+¨H°Q­KÓ8×DÑD×DÑDÓYaùs   ‚;=TF)r\   r]   Ú
ValueErrorré   rê   ro   rë   Ú_socketÚgetaddrinfoÚ	AF_UNSPECÚSOCK_STREAMÚanyÚgaierrorr^   )rã   ÚaddrÚmappedÚresolveds   &   r   Úis_network_accessiblerû   þ   sÓ   € ô 
×	Ò	œZ×	(Õ	(Ü×#Ò# DÓ)ˆä˜˜}¨dÓ3ˆØ×$Ñ$×GÐG¨×)FÐ)F°F×4FÑ4FÔH÷	 
)×	(×	(Ò	(úð
Ü×&Ò& t¨T´7×3DÑ3DÄg×FYÑFYÓZˆç‹sÑbÑYaÓb�sŒsÐbŠsÐbˆsÑbÑYaÓbÓbÐbøÜ×ÑœgÐ&ô Úðús<   £A B Á$B Â B	Â?C= ÃC= Ã(C= Ã+C= Ã/C= Ã=DÄDg      N@c                ó2   € V ^8„  d   QhR\         R,          /# r‘   rk   )r   s   "r   r   r     s   € ÷  ñ  ¤C¨$¥Jñ  r   c            	     óÌ  € \         P                  R8w  d   R# \        p \        P                  ! 4       pV e"   W^ ,          ,
          \
        8  d
   V ^,          #  \        P                  ! RR.^RRR\        P                  R7      pR	 TP                  4        4        UUUu/ uF.  w  r4qT'       g   K  TP                  4       TP                  4       bK0  	  ppppRpR Fd  w  r‰p
TP                  T4      R
8X  g   K  TP                  T	4      '       g   K7  TP                  T
4      '       g   KP  RYi,           RYj,           2p M	  Y3sT#   \         d	    TR3s R# i ; iu upppi )a  Read the macOS system HTTP(S) proxy via ``scutil --proxy``: ``http://host:port``
when an HTTP(S) proxy is enabled, else None (non-macOS or any subprocess error).

Memoised for ``_MACOS_PROXY_TTL_SECONDS``; call :func:`reset_macos_proxy_cache` to force a re-read.
ÚdarwinNÚscutilz--proxyTrH   rI   )r3   ÚtextÚencodingrK   rY   c              3   ó^   "  € T F#  qP                  4       P                  R 4      x € K%  	  R# 5i)z : N)r‹   Ú	partition)rì   Úlines   & r   rï   Ú-_detect_macos_system_proxy.<locals>.<genexpr>/  s$   é € ÐYÑHXÀŸj™j›l×4Ñ4°U×;Ð;ÓHXùs   ‚+-r@   zhttp://Ú:))ÚHTTPSEnableÚ
HTTPSProxyÚ	HTTPSPort)Ú
HTTPEnableÚ	HTTPProxyÚHTTPPort)Úsysrq   Ú_macos_proxy_cacheÚtimeÚ	monotonicÚ_MACOS_PROXY_TTL_SECONDSrS   Úcheck_outputrU   r[   Ú
splitlinesr‹   r¥   )ÚcachedÚnowÚoutÚkeyÚsepÚvalÚpropsrú   Ú
enable_keyÚhost_keyÚport_keys              r   Ú_detect_macos_system_proxyr    sP  € ô ‡|�|�xÔÙÜ€FÜ
�.Š.Ó
€CØÒ˜s¨A¥Y�Ô2JÔJØ�a�yÐðÜ×%Ò% x°Ð&;ÀQÈTÐ\cØ-6¼z×?QÑ?QôSˆñ ZÈÏÉÔHXÔYõbáY‰MˆC�cÓ]`ô 	!ˆ�	‰	‹�S—Y‘Y“[Ò ÙYð 
ò bð €Hó+]Ñ&ˆ
˜hà�9‰9�ZÓ  CÖ'¨E¯I©I°h×,?Ô,?ÀEÇIÁIÈh×DWÔDWØ  ¥Ð 1°°5µ?Ð2CÐDˆHÙñ	+]ð
 ˜ÐØ€Oøô ô à! 4˜[ÐÚðüôbs   Á,E	 Â EÂ1#EÅ	EÅEc                ó   € V ^8„  d   QhRR/# r‘   rt   )r   s   "r   r   r   ;  s   € ÷ ñ  ñ r   c                 ó
   € Rs R# )zIDrop the memoised ``scutil --proxy`` answer so the next call re-reads it.N)r  rt   r   r   Úreset_macos_proxy_cacher!  ;  s
   € ð Òr   c                óÆ   € V ^8„  d   QhR\         \        \         ,          ,          \        \         R3,          ,          \        \         ,          ,          R,          R\        /# )r   Útarget_hosts.Nr   )r8   ÚlistÚtupleÚsetrµ   )r   s   "r   r   r   B  s?   € ÷ .ñ .¤c¬D´­I¥o¼¼cÀ3¸h½Õ&GÌ#ÌcÍ(Õ&RÐUYÕ&Yð .Ô^bñ .r   c                ó   € \        V 4      # )z¤True when NO_PROXY/no_proxy matches at least one target host (exact hosts, domain /
wildcard suffixes, IP literals, CIDR ranges, optional host:port entries, ``*``).©Ú_should_bypass_proxy)r#  s   &r   r   r   B  s   € ô   Ó-Ð-r   r#  Ú
configuredc          	      ó  € V ^8„  d   QhR\         R,          R\         \        \         ,          ,          \        \         R3,          ,          \        \         ,          ,          R,          R\         R,          R\         R,          /# )r   Úplatform_env_varNr#  .r*  r   )r8   r$  r%  r&  )r   s   "r   r   r   H  se   € ÷ Jñ JÜ˜D•jðJäœœS�	•/¤E¬#¨s¨(¥OÕ3´c¼#µhÕ>ÀÕEðJô �d•
ðJô '*¨D¥jñJr   c               óv  € ^ RI Hp V '       d"   V! V R4      ;'       g    RP                  4       MRpV'       g$   \        T;'       g    R4      P                  4       pV'       g   \	        4       '       g   R# \        4       p\        T;'       g    \        4       4      pV'       d   \        V4      '       d   R# T# )uÉ  Proxy URL: *platform_env_var* (e.g. ``DISCORD_PROXY``) first, then the adapter's own YAML
value *configured* (``telegram.proxy_url``), then HTTPS_PROXY / HTTP_PROXY / ALL_PROXY (any
case), then the macOS system proxy â€” the latter two only when ``gateway.trust_env`` is true.
None when nothing is found or NO_PROXY matches a target.

*platform_env_var* is a per-adapter, per-profile-configurable setting (each proxy URL can
embed credentials, e.g. ``http://user:pass@host``) so it is read scope-aware: under a
secondary multiplex profile it comes from that profile's own ``.env``, not the shared
process env another profile's ``TELEGRAM_PROXY``/``DISCORD_PROXY``/etc. may hold; the YAML
value is the same profile's, so a secondary keeps its configured route without any env
bridge (#108440). The generic ``HTTPS_PROXY``/``HTTP_PROXY``/``ALL_PROXY`` fallback stays a raw
process-env read â€” those are OS/system-level network settings, not a per-profile Hermes concept.)Úget_scoped_secretrn   N)	Úgateway.platforms._sharedr.  r‹   r8   Úgateway_trust_envr
   r   r  r   )r,  r#  r*  Ú_get_scoped_proxy_varrm   Úproxys   &$$   r   Úresolve_proxy_urlr3  H  s�   € õ  UßK[Ñ"Ð#3°RÓ8×>Ð>¸B×EÑEÔGÐac€EßÜ�J×$Ð$ "Ó%×+Ñ+Ó-ˆßÜ ×"Ò"ÙÜ%Ó'ˆÜ × EÐ EÔ)CÓ)EÓF€EßÔ0°×>Ò>ˆ4ÐIÀEÐIr   c                ó$   € V ^8„  d   QhR\         /# )r   Ú	proxy_urlrk   )r   s   "r   r   r   d  s   € ÷ ñ ¬ñ r   c                óÐ   €  ^ RI Hp VP                  V RR7      #   \         d@    T P	                  4       P                  R4      '       d   \        P                  RT 4        R# i ; i)u  ``aiohttp_socks.ProxyConnector`` for ``proxy_url``, or None when aiohttp_socks is missing
(SOCKS logs a warning; HTTP callers fall back to ``proxy=``). ``rdns=True`` forces remote DNS
through the proxy â€” required by Shadowrocket/Clash-style SOCKS and against GFW DNS pollution.)ÚProxyConnectorT)ÚrdnsÚsocksuR   aiohttp_socks not installed â€” SOCKS proxy %s ignored. Use an HTTP proxy instead.N)Úaiohttp_socksr7  Úfrom_urlÚImportErrorrp   Ú
startswithr   rX   )r5  r7  s   & r   Ú_aiohttp_socks_connectorr>  d  s_   € ðÝ0Ø×&Ñ& y°tÐ&Ó<Ð<øÜô Ø�?‰?Ó×'Ñ'¨×0Ò0Ü�N‰Nð 8Ø9BôDâð	ús   ‚ ›/A%ÁA%Á$A%c                ó>   € V ^8„  d   QhR\         R,          R\        /# ©r   r5  Nr   r{   )r   s   "r   r   r   r  s   € ÷  ñ  ¤C¨$¥Jð  ´4ñ  r   c                ó’   € V '       g   / # V P                  4       P                  R4      '       d   \        V 4      pVe   RV/# / # RV /# )u€   Kwargs for ``commands.Bot()`` / ``discord.Client()``: SOCKS â†’ ``{"connector"}``,
HTTP â†’ ``{"proxy": url}``, None â†’ ``{}``.r9  Ú	connectorr2  )rp   r=  r>  ©r5  rB  s   & r   Úproxy_kwargs_for_botrD  r  sN   € ÷ Øˆ	Ø‡�Ó×#Ñ# G×,Ò,Ü,¨YÓ7ˆ	Ø+4Ò+@�˜YÐ'ÐHÀbÐHØ�YÐÐr   c                ó0   € V ^8„  d   QhR\         R\        /# )r   Únamer   r{   )r   s   "r   r   r   }  s   € ÷ 8ñ 8œ#ð 8¤$ñ 8r   c                óÊ   €  ^ RI Hp V! 4       p\        T\        4      '       d   TP                  T 4      MRp\        T\        4      '       d   T# / #   \         d    / u # i ; i)zVRead-only ``config.yaml`` section ``name``; ``{}`` when unreadable/missing/not a dict.)Úload_config_readonlyN)Úhermes_cli.configrH  r[   r¤   r|   r¥   )rF  Ú_load_configÚcfgÚsections   &   r   Ú_config_sectionrM  }  s[   € ðÝJÙ‹nˆô  *¨#¬t×4Ò4ˆc�g‰g�dŒm¸$€GÜ  ¬$×/Ò/ˆ7Ð7°RÐ7øô ô ØŠ	ðús   ‚A ÁA"Á!A"c                ó$   € V ^8„  d   QhR\         /# rj   ©rµ   )r   s   "r   r   r   ˆ  s   € ÷ 6ñ 6œ4ñ 6r   c                 óÈ   € \        R4      P                  RR4      p \        V \        4      '       d"   V P	                  4       P                  4       R9  # V e   \        V 4      # R# )zè``gateway.trust_env`` from config.yaml (default True): whether gateway
``aiohttp.ClientSession``s honor HTTP(S)_PROXY / NO_PROXY / SSL_CERT_FILE. Set false
when the gateway inherits a proxy env it must not use. Fail-open to default.ÚgatewayÚ	trust_envT>   Ú0ÚnoÚoffÚfalse)rM  r¥   r¤   r8   r‹   rp   rµ   ©rm   s    r   r0  r0  ˆ  sW   € ô ˜IÓ&×*Ñ*¨;¸Ó=€EÜ�%œ×ÒØ�{‰{‹}×"Ñ"Ó$Ð,GÑGÐGØÒ+Œ4�‹;Ð5°Ð5r   c                ó`   € V ^8„  d   QhR\         R,          R\        \        \        3,          /# r@  )r8   r%  r|   )r   s   "r   r   r   ’  s+   € ÷ 	]ñ 	]¬¨d­
ð 	]´u¼TÄ4¸ZÕ7Hñ 	]r   c                ó¢   € V '       g   / / 3# \        V 4      pVe   RV// 3# V P                  4       P                  R4      '       d   / / 3# / RV /3# )a	  ``(session_kwargs, request_kwargs)`` for a standalone ``aiohttp.ClientSession``. With
aiohttp-socks every scheme uses a connector (mautrix-style libs never forward per-request
``proxy=``); without it HTTP falls back to ``({}, {"proxy": url})`` and SOCKS is ignored.rB  r9  r2  )r>  rp   r=  rC  s   & r   Úproxy_kwargs_for_aiohttprZ  ’  sa   € ÷ Ø�2ˆvˆÜ(¨Ó3€IØÒØ˜YÐ'¨Ð+Ð+Ø —‘Ó(×3Ñ3°G×<Ò<ˆB�ˆ8Ð\À2ÈÐQZÐG[ÐB\Ð\r   c                óJ   € V ^8„  d   QhR\         R\         R,          R\        /# )r   ÚhostnameÚno_proxy_valueNr   r´   )r   s   "r   r   r   ž  s+   € ÷ Iñ I¬3ð IÄÀdÅ
ð IÔVZñ Ir   c                ó   € \        WR7      # )z—Return True when ``hostname`` matches a ``NO_PROXY`` entry (``no_proxy_value`` overrides the
environment); same matcher as :func:`should_bypass_proxy`.)r]  r(  )r\  r]  s   &&r   Úis_host_excluded_by_no_proxyr_  ž  s   € ô   ÔHÐHr   )Ú	dataclass©ÚPath)	ÚTYPE_CHECKINGÚDictÚListÚOptionalÚAnyÚCallableÚ	AwaitableÚTupleÚUnion)ÚPlatformÚPlatformConfig)Úfence_state_after)Úapproval_timeout_secondsÚea_action_labelsÚea_default_reason_textÚea_header_textÚea_reason_label_textÚea_smart_deny_line_textÚformat_approval_deadline_line)ÚAudioFormatÚStreamingTTSHandleÚ$streaming_tts_should_skip_whole_fileÚstreaming_tts_turn_key)ÚMessageEventÚMessageTypeÚProcessingOutcome)Údiagnostic_wake_muted)Úrecords_deliveryÚstop_reply_clock)ÚSessionSourceÚbuild_session_key)ÚTranscriptReadError)ÚCONNECTOR_DOWNLOADS_SUBDIRÚget_default_hermes_rootÚget_hermes_dirÚget_hermes_home)ÚGENERATED_SUBDIRÚMEDIA_CACHE_MAX_AGE_HOURS)ÚToolPreviewz�Secure secret entry is not supported over messaging. Load this skill in the local CLI to be prompted, or add the key to ~/.hermes/.env manually.z­This bot is private and you're not on its allowed list. If you own it, run `hermes pairing approve {platform} <request-id>` on the host (`hermes pairing list` shows the id).c                ó0   € V ^8„  d   QhR\         R\        /# )r   rq   r   )rg  r8   )r   s   "r   r   r   Ë  s   € ÷ Wñ W¬ð W´ñ Wr   c                ó\   € \        V RV 4      p\        R\        T;'       g    R4      R7      # )u¨   Localized ``UNAUTHORIZED_ACTION_NOTICE`` for a ``Platform`` member or its string name.
Call it per refusal â€” never bind the result at import, or the language freezes.rm   z"gateway.unauthorized.action_noticez
<platform>)rq   )ro   r   r8   )rq   rF  s   & r   Úunauthorized_action_noticerŒ  Ë  s-   € ô �8˜W hÓ/€DÜÐ1¼CÀ×@TÐ@TÈÓ<UÔVÐVr   c              ƒ  óŒ   "  € ^ RI HpHp V! V 4      pV'       d(   V! V4      '       g   \        R\	        V4       24      hR# R# 5i)z®Re-validate each redirect target (a public URL 302-ing to http://169.254.169.254/ would
bypass the pre-flight is_safe_url()). Async because httpx awaits response event hooks.)Úis_safe_urlÚredirect_target_from_responsez.Blocked redirect to private/internal address: N)Útools.url_safetyrŽ  r�  rñ   r   )ÚresponserŽ  r�  Úredirect_urls   &   r   Ússrf_redirect_guardr“  Ò  sD   é € ÷ LÙ0°Ó:€Lß™K¨×5Ò5ÜÐIÔJZÐ[gÓJhÐIiÐjÓkÐkñ 6�|ùs
   ‚&A©Azcache/imagesÚimage_cachec                ó$   € V ^8„  d   QhR\         /# rj   ©r9   )r   s   "r   r   r   î  s   € ÷ [ñ [¤Sñ [r   c                 óD   € \        R \        \        \        \        34      # )u�   Max inbound media bytes held in memory (``gateway.max_inbound_media_bytes``);
``0`` / negative / unparseable disables the cap; unreadable config â†’ default.c                  ó8   € \        \        R 4      R,          4      # )rQ  Úmax_inbound_media_bytes)r9   rM  rt   r   r   Ú<lambda>Ú-get_inbound_media_max_bytes.<locals>.<lambda>ñ  s   € œs¤?°9Ó#=Ð>WÕ#XÔYr   )rw   ÚDEFAULT_INBOUND_MEDIA_MAX_BYTESÚKeyErrorÚ	TypeErrorrñ   rt   r   r   Úget_inbound_media_max_bytesrŸ  î  s"   € ô ÑYÜ6¼Ä9ÌjÐ8Yó[ð [r   Ú
media_typeÚmediaÚ	max_bytesc                óV   € V ^8„  d   QhR\         R\        R\        \         ,          RR/# )r   Úsizer   r¢  r   N)r9   r8   rf  )r   s   "r   r   r   õ  s6   € ÷ fñ fÜ
ðfÜ!ðfÜ8@Ä½ðfØQUñfr   c          	     óp   € Vf   \        4       MTpV'       d   W8”  d   \        RV RV  RV R24      hR# R# )z©Raise ``ValueError`` if an inbound payload exceeds the cap (``max_bytes`` of ``0``
disables it; pass it explicitly to resolve the limit once across an incremental read).NzInbound z payload is too large (z	 bytes > z bytes))rŸ  rñ   )r¤  r   r¢  rß   s   &$$ r   Úvalidate_inbound_media_sizer¦  õ  sF   € ð .7Ò->Ô'Ô)ÀI€Eß�”Ü˜8 J <Ð/FÀtÀfÈIÐV[ÐU\Ð\cÐdÓeÐeñ �ur   c                ó0   € V ^8„  d   QhR\         R\        /# )r   r   r   )r8   Úbytes)r   s   "r   r   r   þ  s   € ÷ ñ ¼sð Äuñ r   c             ƒ  ó¬  "  € \        4       pV P                  P                  R4      pV'       d    \        V4      p\	        WAVR7       . p^ pV P                  4         Rj  x€L
  pV\        V4      ,          p\	        WaVR7       VP                  V4       K<    \
         d    \        P                  RY4        Lsi ; i L^D_RP                  T4      # 5i)zµRead an httpx streaming body under the media cap: reject an oversized ``Content-Length``
early, then re-check the running total per chunk (a lying/absent header can't smuggle more).zcontent-length)r   r¢  z2Ignoring invalid Content-Length for inbound %s: %rNr   )rŸ  Úheadersr¥   r9   r¦  rñ   r   ÚdebugÚaiter_bytesrÒ   ÚappendrÆ   )r‘  r   r¢  Úcontent_lengthÚdeclared_sizeÚchunksÚtotalÚchunks   &$      r   Ú_read_httpx_body_with_limitr³  þ  sÇ   é € ô ,Ó-€IØ×%Ñ%×)Ñ)Ð*:Ó;€Nßð	cÜ Ó/ˆMô (¨ÐXaÕbØ€FØ€EØ×+Ñ+Ô-÷ ð ˆeØ”�U“ÕˆÜ# EÈIÕVØ�‰�eÖøô ô 	kÜ�L‰LÐMÈzÖjð	kúñÐ-ð �8‰8�FÓÐùsK   ‚.C±B ¼!CÁCÁ!C Á"CÁ%4CÂ!B=Â:CÂ<B=Â=CÃ CÃCc                óH   € V ^8„  d   QhR\         R\         R\         R\         /# )r   r«   Úconstant_nameÚnew_subpathÚold_namerk   )r   s   "r   r   r     s)   € ÷ ñ œsð ´3ð ÄSð ÔTWñ r   c                ó�   aaaa€ R VVV3R llo\         3R V3R lllpRV  R2;Sn        Sn        RV  R2;Vn        Vn        SV3# )	aB  ``(get_<kind>_cache_dir, cleanup_<kind>_cache)`` pair. The getter resolves fresh via
get_hermes_dir (active profile) unless a test monkeypatched the module constant away from
its import-time default, and creates the directory; ``cleanup(max_age_hours=MEDIA_CACHE_MAX_AGE_HOURS)`` deletes
older files and returns the count.c                ó$   € V ^8„  d   QhR\         /# rj   ra  )r   s   "r   r   Ú*_cache_dir_accessors.<locals>.__annotate__  s   € ÷ ñ ”Tñ r   c                  óÄ   <€ \        SS4      p \        4       P                  S4      p\        P                  S4      pVe   Ve   W8w  d   \	        V4      p \        V 4       V # ©N)r…  Úglobalsr¥   Ú_CACHE_DIR_IMPORT_DEFAULTSrb  Ú_secure_media_cache_dir)ÚdÚcurrentrv   rµ  r¶  r·  s      €€€r   Úget_dirÚ%_cache_dir_accessors.<locals>.get_dir  sU   ø€ Ü˜;¨Ó1ˆÜ“)—-‘- Ó.ˆÜ,×0Ñ0°Ó?ˆØÒ 7Ò#6¸7Ô;MÜ�W“ˆAÜ Ô"Øˆr   c                ó0   € V ^8„  d   QhR\         R\         /# )r   Úmax_age_hoursr   r–  )r   s   "r   r   rº  !  s   € ÷ <ñ <œsð <Ä3ñ <r   c                 ó&   <€ \        S! 4       V 4      # r¼  )Ú_cleanup_cache_dir)rÅ  rÂ  s   &€r   ÚcleanupÚ%_cache_dir_accessors.<locals>.cleanup!  s   ø€ Ü!¡'£)¨]Ó;Ð;r   Úget_Ú
_cache_dirÚcleanup_Ú_cache)rˆ  Ú__name__Ú__qualname__)r«   rµ  r¶  r·  rÈ  rÂ  s   &fff @r   Ú_cache_dir_accessorsrÐ    sY   û€ ÷
ò ô &?÷ <ò <à04°T°F¸*Ð.EÐE€GÔ�wÔ+Ø08¸¸¸fÐ.EÐE€GÔ�wÔ+Ø�GÐÐr   ÚIMAGE_CACHE_DIRc                ó0   € V ^8„  d   QhR\         R\        /# )r   Údatar   )r¨  rµ   )r   s   "r   r   r   ,  s   € ÷ Wñ WœEð W¤dñ Wr   c                ó:  € \        V 4      ^8¬  ;'       d‡    V R,          R8H  ;'       gs    V R,          R8H  ;'       g_    V R,          R9   ;'       gK    V R,          R8H  ;'       g7    V R,          R	8H  ;'       d#    \        V 4      ^8¬  ;'       d    V R
,          R8H  # )zDReturn True if *data* starts with a known image magic-byte sequence.:Né   Ns   ‰PNG

:Né   Ns   ÿØÿ:Né   N:Nr   Ns   BM:Né   Ns   RIFF:rÕ  rÂ   Ns   WEBP>   ó   GIF87aó   GIF89arØ   )rÓ  s   &r   Ú_looks_like_imagerÛ  ,  s¬   € äˆt‹9˜‰>÷ Wð W˜t B�xÐ+?Ñ?÷  Vð  VÀ4ÈÅ8ÈÑC^÷  Vð  VØ�r•(Ð4Ñ4÷ Vð  VØ8<¸R½ÀEÑ8I÷ Vð  Và˜•8˜wÑ&×TÐT¬3¨t«9¸©?×TÐT¸tÀD½zÈWÑ?TðWr   c                ó(   € V ^8„  d   QhR\         RR/# )r   Ú	cache_dirr   Nra  )r   s   "r   r   r   3  s   € ÷ "5ñ "5¤tð "5°ñ "5r   c                ó´  €  Rp ^ RI Hp \        V! 4       4      pV'       d   V P	                  RRR7       R# \        V RRRR7        ^ RI Hp V! V 4       R#   \         d     LJi ; i  \         d"   p\        P                  R	T4        Rp?R# Rp?ii ; i  \         d5   p\        P                  R
Y4       T P	                  RRR7        Rp?R# Rp?ii ; i)u  Create/reconcile a gateway media-cache dir owner-only (0700), except managed.

Inbound media (photos, voice notes, documents a user sent through a
messaging platform) is user content, not regenerable cache: the
umask-derived 0755 these dirs inherited made them readable by every other
local account whenever ``HERMES_HOME`` is traversable â€” the documented
``HERMES_HOME_MODE=0701`` web-server hatch. The mode is passed to ``mkdir``
so it is set at creation, then reconciled by the house policy helper
``hermes_cli.config._secure_dir`` (managed/NixOS installs keep their
group-share design: these lazily-created dirs are not covered by the
module's ``systemd.tmpfiles`` rules, so the mode is left to the
configured umask/setgid). Best-effort: never fails a media write.
F)Ú
is_managedT)ÚparentsrÄ   NiÀ  )rà  rÄ   Úmode)Ú_secure_dirz!media cache dir chmod skipped: %sz*media cache dir creation failed for %s: %s)	rI  rß  rµ   r[   Úmkdirr   râ  r   r«  )rÝ  Úmanagedrß  râ  r   s   &    r   r¿  r¿  3  sÁ   € ð5Øˆð	Ý4ä™:›<Ó(ˆG÷ Ø�O‰O D°4ˆOÔ8ÙÜ�i¨¸À5ÕIð	CÝ5á˜	Ö"øô ô 	Ùð	ûô ô 	CÜ�L‰LÐ<¸c×BÒBûð	Cûäô 5Ü�‰ÐAÀ9ÔRØ�‰ ¨tˆ×4Ò4ûð5úsg   ‚B …A ›B £B ¸B ÁA) ÁA&Á#B Á%A&Á&B Á)BÁ4BÂ
B ÂBÂB ÂCÂ#)CÃCc          
      óT   € V ^8„  d   QhR\         R\        R\        R\        R\        /# )r   rÝ  r=   r²   rÓ  r   )rb  r8   r¨  )r   s   "r   r   r   X  s/   € ÷ ñ ¤ð ¬sð ¼ð ÄEð Ìcñ r   c                ó$  € W R\         P                  ! 4       P                  R,           V 2,          p \        P                  ! \        V4      \        P                  \        P                  ,          \        P                  ,          R4      p\        P                  ! TR4      ;_uu_ 4       pTP                  T4       RRR4       \        T4      #   \         d     TP                  T4       \        T4      u # i ; i  + '       g   i     LH; i)u«  Write ``data`` to ``<cache_dir>/<prefix>_<uuid12><ext>``; return the path string.

The file is written owner-only (0600) â€” inbound media is private user
content and the cache dir is hardened to 0700 by ``_secure_media_cache_dir``;
one directory should not carry two file-mode conventions. Best-effort on
platforms where POSIX mode bits are advisory (Windows): falls back to a
plain write rather than failing the media write.
rí   rÁ   i€  ÚwbN)rÈ   rÉ   rÊ   rP   Úopenr8   ÚO_WRONLYÚO_CREATÚO_TRUNCr^   Úwrite_bytesÚfdopenÚwrite)rÝ  r=   r²   rÓ  Úfilepathra   Úhandles   &&&&   r   Ú_write_cache_filerñ  X  sÀ   € ð ˜X Q¤t§z¢z£|×'7Ñ'7¸Õ'<Ð&=¸c¸UÐCÕC€HðÜ�WŠW”S˜“]¤B§K¡K´"·*±*Õ$<¼r¿z¹zÕ$IÈ5ÓQˆô 
�Š�2�t×	Ô	 Ø�‰�TÔ÷ 
äˆx‹=Ðøô ô Ø×Ñ˜TÔ"Ü�8‹}Òðú÷ 
×	ús   µAC Â-C?Ã'C<Ã;C<Ã?D	c                ó<   € V ^8„  d   QhR\         R\        R\        /# ©r   rÓ  r²   r   ©r¨  r8   )r   s   "r   r   r   l  s&   € ÷ Fñ F¤ð F¬Sð F¼cñ Fr   c                óÔ   € \        \        V 4      RR7       \        V 4      '       g.   V R,          P                  RRR7      p\	        RV RV: R	24      h\        \        4       R
W4      # )z�Save raw image bytes to the cache and return the absolute path; raises
ValueError when *data* isn't an image (e.g. an upstream HTML error page).r©   ©r   :NéP   NrH   rI   rJ   z$Refusing to cache non-image data as z (starts with: Ú)Úimg)r¦  rÒ   rÛ  rZ   rñ   rñ  Úget_image_cache_dir)rÓ  r²   Úsnippets   && r   Úcache_image_from_bytesrü  l  sg   € ô  ¤ D£	°gÕ>Ü˜T×"Ò"Ø�s•)×"Ñ" 7°9Ð"Ó=ˆÜÐ?À¸uÀOÐT[ÑS^Ð^_Ð`ÓaÐaÜÔ0Ó2°E¸3ÓEÐEr   c                ó<   € V ^8„  d   QhR\         R\        R\        /# ró  rô  )r   s   "r   r   r   v  ó&   € ÷ Fñ F¬Uð F¼ð FÌ#ñ Fr   c              ƒ  óT   "  € \         P                  ! \        W4      G Rj  x€L
 #  L5i)z;Cache image bytes without blocking the caller's event loop.N)r   Ú	to_threadrü  ©rÓ  r²   s   &&r   Úcache_image_from_bytes_asyncr  v  ó   é € ä×"Ò"Ô#9¸4ÓE×EÐEÑEùó   ‚(¡&¢(c                ól   € V ^8„  d   QhR\         R\         R\        R\         R\         R\         R\         /# )r   Úurlr²   Úretriesr   ÚacceptÚ	log_labelr   r7   )r   s   "r   r   r   {  sA   € ÷ ñ ¤Sð ¬sð ¼Sð ÔQTð Ô^að Ü58ðÜ=@ñr   c             ƒ  ó>  "  € ^ RI HpHp ^ RIp	V! V 4      '       g   \	        R\        V 4       24      hRRRV/p
V! RRR	\        ./R
7      ;_uu_4       GRj  x€L
 p\        V^,           4       FŽ  p VP                  RW
R7      ;_uu_4       GRj  x€L
 pVP                  4        \        WÓR7      G Rj  x€L
 pRRR4      GRj  x€L
  \        P                  ! VXV4      G Rj  x€L
 u uuRRR4      GRj  x€L
  # 	  RRR4      GRj  x€L
  R#  Lº L‚ L` LR  + GRj  x€L 
 '       g   i     Li; i LP L?  T	P                  T	P                  3 d¤   p\        YùP                  4      '       d   TP                   P"                  R8  d   h YÂ8  da   RT^,           ,          p\$        P'                  RYl^,           T\        T 4      TT4       \        P(                  ! T4      G Rj  x€L 
   Rp?EK†  h Rp?ii ; i Lñ  + GRj  x€L 
 '       g   i     R# ; i5i)z¨Shared downloader behind ``cache_*_from_url``: SSRF-checked (pre-flight + per-redirect;
raises ValueError), size-capped, linear-backoff retries on timeouts / 429 / 5xx.)Úcreate_ssrf_safe_async_clientrŽ  Nz&Blocked unsafe URL (SSRF protection): z
User-Agentz)Mozilla/5.0 (compatible; HermesAgent/1.0)ÚAcceptrg   Tr‘  )r3   Úfollow_redirectsÚevent_hooksÚGET)rª  rö  i­  ç      ø?z'%s cache retry %d/%d for %s (%.1fs): %s)r�  r  rŽ  Úhttpxrñ   r   r“  ÚrangeÚstreamÚraise_for_statusr³  r   r   ÚTimeoutExceptionÚHTTPStatusErrorr¤   r‘  Ústatus_coder   r«  Úsleep)r  r²   r  r   r  Úcache_fnr	  r  rŽ  r  rª  ÚclientÚattemptr‘  Úcontentr   Úwaits   &&&$$$$          r   Ú_cache_media_from_urlr  {  sÇ  é € ÷ LÛÙ�s×ÒÜÐAÔBRÐSVÓBWÐAXÐYÓZÐZØÐHÈ(ÐTZÐ[€GÙ,Ø t¸*ÔGZÐF[Ð9\÷÷ õ à	Ü˜W q�[Ö)ˆGðØ!Ÿ=™=¨°˜=×E×EÔEÈØ×-Ñ-Ô/Ü$?ÀÔ$`×`�G÷ F×Eô %×.Ò.¨x¸À#ÓF×FÑF÷÷ ò ñ *÷÷ ó ñ
 Fá`÷ F×E×EÒEúñ Gñøð ×*Ñ*¨E×,AÑ,AÐBô 	Ü˜c×#8Ñ#8×9Ò9¸c¿l¹l×>VÑ>VÐY\Ô>\ØØÔ$Ø '¨A¥+Õ.�DÜ—L‘LÐ!JÈIÐabÕWbØ!(Ô*:¸3Ó*?ÀÀsôLä!Ÿ-š-¨Ó-×-Ñ-ÞØûð	ú÷÷ ÷ ó üs  ‚AHÁDÁHÁH Á3D;ÂDÂD;Â DÂ6DÂ7DÂ;D;ÃD
ÃD;Ã&D7
Ã'D;Ã*H Ã,HÃ9D9Ã:HÃ?H ÄHÄG>ÄHÄD;ÄDÄD;ÄD4Ä!D$Ä"
D4Ä-D4Ä/	D;Ä9HÄ;G;	ÅBG6	Ç(G+Ç)G6	Ç.H Ç5G6	Ç6G;	Ç;H Ç>HÈ H	ÈH	È
H	ÈH	È	Hc                óH   € V ^8„  d   QhR\         R\         R\        R\         /# ©r   r  r²   r  r   r7   )r   s   "r   r   r   ™  ó)   € ÷ <ñ <¤Cð <¬cð <ÄSð <ÔQTñ <r   c           
   ƒ  óH   "  € \        WVRR\        RR7      G Rj  x€L
 #  L5i)zEDownload an image URL into the image cache; return the absolute path.r©   zimage/*,*/*;q=0.8ÚMedia©r   r  r  r	  N)r  rü  ©r  r²   r  s   &&&r   Úcache_image_from_urlr&  ™  ó+   é € ä&Ø�' gÐ6IÜ'°7ô<÷ <ð <ñ <ùó   ‚"› œ"c                ó<   € V ^8„  d   QhR\         R\        R\        /# )r   rÝ  rÅ  r   )rb  r9   )r   s   "r   r   r      s!   € ÷ 	ñ 	¤$ð 	´sð 	¼sñ 	r   c                ó   € \         P                   ! 4       VR,          ,
          p^ pV P                  4        F€  pVP                  4       '       g   K  VP                  4       P                  V8  g   K<  \
        P                  ! \        4      ;_uu_ 4        VP                  4        V^,          pRRR4       K‚  	  V#   + '       g   i     K—  ; i)zQDelete files in *cache_dir* older than *max_age_hours*; return the count removed.i  N)	r  ÚiterdirÚis_fileÚstatÚst_mtimer\   r]   r^   r_   )rÝ  rÅ  ÚcutoffÚremovedÚfs   &&   r   rÇ  rÇ     s‹   € ä�YŠY‹[˜M¨DÕ0Õ1€FØ€GØ×ÑÖ ˆØ�9‰9�;Œ;˜1Ÿ6™6›8×,Ñ,¨vÖ5Ü×$Ò$¤W×-Õ-Ø—‘”
Ø˜1•�÷ .Ñ-ñ !ð
 €N÷ .×-Ð-ús   ÂB<Â<Czcache/audioÚaudio_cacheÚAUDIO_CACHE_DIRc                ó<   € V ^8„  d   QhR\         R\        R\        /# ró  rô  )r   s   "r   r   r   ²  s&   € ÷ _ñ _¤ð _¬Sð _¼cñ _r   c                ór   € ^ RI Hp \        \        V 4      RR7       \	        \        4       RV! W4      V 4      # )zKSave raw audio bytes to the cache (container-sniffed ext); return the path.)Úsniff_audio_extr§   rö  )Útools.audio_containerr6  r¦  rÒ   rñ  Úget_audio_cache_dir)rÓ  r²   r6  s   && r   Úcache_audio_from_bytesr9  ²  s0   € õ 6Ü¤ D£	°gÕ>ÜÔ0Ó2°G¹_ÈTÓ=WÐY]Ó^Ð^r   c                ó<   € V ^8„  d   QhR\         R\        R\        /# ró  rô  )r   s   "r   r   r   º  rþ  r   c              ƒ  óT   "  € \         P                  ! \        W4      G Rj  x€L
 #  L5i)z;Cache audio bytes without blocking the caller's event loop.N)r   r   r9  r  s   &&r   Úcache_audio_from_bytes_asyncr<  º  r  r  c                óH   € V ^8„  d   QhR\         R\         R\        R\         /# r   r7   )r   s   "r   r   r   ¿  r!  r   c           
   ƒ  óH   "  € \        WVRR\        RR7      G Rj  x€L
 #  L5i)zEDownload an audio URL into the audio cache; return the absolute path.r§   zaudio/*,*/*;q=0.8ÚAudior$  N)r  r9  r%  s   &&&r   Úcache_audio_from_urlr@  ¿  r'  r(  zcache/videosÚvideo_cacheÚVIDEO_CACHE_DIRz	video/mp4zvideo/quicktimez
video/webmzvideo/x-matroskazvideo/x-msvideoc                ó<   € V ^8„  d   QhR\         R\        R\        /# ró  rô  )r   s   "r   r   r   Ð  s&   € ÷ Hñ H¤ð H¬Sð H¼cñ Hr   c                óX   € \        \        V 4      RR7       \        \        4       RW4      # )zDSave raw video bytes to the cache and return the absolute file path.r¨   rö  )r¦  rÒ   rñ  Úget_video_cache_dirr  s   &&r   Úcache_video_from_bytesrF  Ð  s#   € ä¤ D£	°gÕ>ÜÔ0Ó2°G¸SÓGÐGr   c                ó<   € V ^8„  d   QhR\         R\        R\        /# ró  rô  )r   s   "r   r   r   Ö  rþ  r   c              ƒ  óT   "  € \         P                  ! \        W4      G Rj  x€L
 #  L5i)z;Cache video bytes without blocking the caller's event loop.N)r   r   rF  r  s   &&r   Úcache_video_from_bytes_asyncrI  Ö  r  r  zcache/documentsÚdocument_cachezcache/screenshotsÚbrowser_screenshotsÚdocumentÚDOCUMENT_CACHE_DIRÚ
screenshotÚSCREENSHOT_CACHE_DIRÚHERMES_MEDIA_ALLOW_DIRSÚHERMES_MEDIA_TRUST_RECENT_FILESÚ!HERMES_MEDIA_TRUST_RECENT_SECONDSÚHERMES_MEDIA_DELIVERY_STRICTÚimagesÚvideosÚ	documentsÚscreenshotsc              #   ó<   "  € T F  p\         V,          x € K  	  R # 5ir¼  ©Ú_HERMES_HOME©rì   rÀ  s   & r   rï   rï   ø  s#   é € ð _ñ !^˜1„l�Q×Òó !^ùs   ‚c              #   óJ   "  € T F  p\         R ,          V,          x € K  	  R# 5i©ÚcacheNrY  r[  s   & r   rï   rï   û  s   é € ÐHÑ*G Q„l�WÕ˜q× Ò Ó*Gùó   ‚!#iX  c                óJ   € V ^8„  d   QhR\         R\        \         R3,          /# )r   rF  r   .)r8   r%  )r   s   "r   r   r     s&   € ÷ Cñ Cœð C¤¤c¨3 h¥ñ Cr   c                ó   € W  R2V  R2V  R23# )z:A SQLite store plus its WAL/SHM/rollback-journal sidecars.z-walz-shmz-journalrt   )rF  s   &r   Ú_sqlite_filesrb    s"   € à�F˜$�- D 6¨ °4°&¸Ð0AÐBÐBr   z.envz	auth.jsonz	auth.lockÚcredentialszconfig.yamlz.anthropic_oauth.jsonzgoogle_token.jsonzgoogle_oauth_pending.jsonÚauthzgoogle_oauth.jsonzwebhook_subscriptions.jsonr^  zbws_cache.jsonzbws_cache.enc.jsonÚpairingz
mcp-tokensÚsessionszbrowser-profilezstate.dbú	kanban.dbc                ó:   € V ^8„  d   QhR\         \        ,          /# rj   ©r$  rb  )r   s   "r   r   r     s   € ÷ ^ñ ^œd¤4�jñ ^r   c                 ó`   € . R \        4        4       OR \        4       .\        4       O 4       O# )an  Per-profile cache roots ``<root>/profiles/<name>/cache/{images,...}`` and every home's connector
downloads dir (the static safe roots cover only the launch HERMES_HOME). Enumerated at check
time so profiles created after startup count, and allowlisted BEFORE the ``/root`` denylist,
which otherwise wins when HERMES_HOME is symlinked under a denied prefix (#31733).
c              3   óZ   "  € T F!  p\          F  q!R ,          V,          x € K  	  K#  	  R# 5ir]  )Ú_MEDIA_DELIVERY_CACHE_SUBDIRS)rì   ÚpÚsubdirs   &  r   rï   Ú'_profile_cache_roots.<locals>.<genexpr>%  s%   é € Ðh©O q×JgÀ�'�k˜F×"Ò"ÑJgÑ"«Oùs   ‚)+c              3   ó:   "  € T F  q\         ,          x € K  	  R # 5ir¼  )rƒ  ©rì   rm  s   & r   rï   ro  &  s   é € Ð\Ñ6[°Ô,×,Ò,Ó6[ùó   ‚)Ú_profile_dirsr†  rt   r   r   Ú_profile_cache_rootsrt    s9   € ð^Ñh¬M¬OÓhð ^Ù\´Ó7HÐ6[Ì=Ë?Ñ6[Ó\ð^ð ^r   c                ó:   € V ^8„  d   QhR\         \        ,          /# rj   ri  )r   s   "r   r   r   )  s   € ÷ ñ ”tœD•zñ r   c                 ó¸   €  \         R,          P                  4        U u. uF  q P                  4       '       g   K  V NK  	  up # u up i   \         d    . u # i ; i)z?Every ``<root>/profiles/<name>`` directory, read at check time.Úprofiles)Ú_HERMES_ROOTr+  Úis_dirr^   ©rm  s    r   rs  rs  )  sK   € ðÜ(¨:Õ5×>Ñ>Ô@ÓOÑ@�aÇHÁHÇJ—�Ñ@ÑOÐOùÒOøÜô ØŠ	ðús'   ‚A	 ŸA»AÁA	 ÁA	 Á	AÁAc                ó:   € V ^8„  d   QhR\         \        ,          /# rj   ri  )r   s   "r   r   r   1  s   € ÷ Tñ T¤¤T¥
ñ Tr   c                 óp   € \        \        P                  \        4       \        .\        4       O54      4      # )u±  Every Hermes home whose credential stores the denylist must cover: the ACTIVE home
(the per-turn HERMES_HOME override under ``gateway.multiplex_profiles``), the shared root
and every ``<root>/profiles/*``. Enumerated at check time like ``_profile_cache_roots`` on
the allow side â€” a denylist frozen at import covers only the launch profile, so a
``MEDIA:<root>/profiles/<other>/.env`` emitted in any profile's turn would upload it.)r$  r|   Úfromkeysr†  rx  rs  rt   r   r   Ú_credential_home_rootsr~  1  s'   € ô ”—‘œÓ0´,ÐQÄÃÑQÓRÓSÐSr   c                ó$   € V ^8„  d   QhR\         /# rj   ra  )r   s   "r   r   r   :  s   € ÷ _ñ _”dñ _r   c                 ó¨   € \        \        P                  P                  RR4      P	                  4       ;'       g    \
        4      P                  4       # )zLKanban is root-shared across profiles by design (``kanban_db.kanban_home``).ÚHERMES_KANBAN_HOMErn   )rb  rP   Úenvironr¥   r‹   rx  Ú
expanduserrt   r   r   Ú_kanban_rootr„  :  s7   € ä”—
‘
—‘Ð3°RÓ8×>Ñ>Ó@×PÐPÄLÓQ×\Ñ\Ó^Ð^r   c                ó:   € V ^8„  d   QhR\         \        ,          /# rj   ri  )r   s   "r   r   r   ?  s   € ÷ ñ œD¤�Jñ r   c                 ó(  € \         P                  ! \        4      ;_uu_ 4        \        4       R,          R,          P	                  4        U u. uF  q P                  4       '       g   K  V NK  	  up uuRRR4       # u up i   + '       g   i     . # ; i)z”Every directory under ``<root>/kanban/boards`` (lax on purpose: the DENY side must catch a
board whatever its name; the allow side filters further).ÚkanbanÚboardsN)r\   r]   r^   r„  r+  ry  rz  s    r   Ú_kanban_board_dirsr‰  ?  s_   € ô 
×	Ò	œW×	%Õ	%Ü(›N¨XÕ5¸Õ@×IÑIÔKÓZÑK�aÏxÉxÏz—�ÑKÑZ÷ 
&Ò	%ùÚZ÷ 
&Ö	%à€Iús#   £)B ÁA;Á(A;Á.B Á;B Â B	c                ó:   € V ^8„  d   QhR\         \        ,          /# rj   ri  )r   s   "r   r   r   G  s   € ÷ 	ñ 	¤$¤t¥*ñ 	r   c                 ó  € \         P                  P                  RR4      P                  4       p V '       d   \	        V 4      P                  4       .# \        4       R,          R,          .pVP                  R \        4        4       4       V# )zCReturn durable Kanban attachment roots without importing kanban_db.ÚHERMES_KANBAN_ATTACHMENTS_ROOTrn   r‡  Úattachmentsc              3   óô   "  € T Fn  pVP                  4       '       d   K  \        P                  ! R VP                  4      '       g   KD  VR,          P	                  4       '       g   Kc  VR,          x € Kp  	  R# 5i)z[a-z0-9][a-z0-9_-]{0,63}rg  r�  N)Ú
is_symlinkÚreÚ	fullmatchrF  r,  )rì   r6   s   & r   rï   Ú+_kanban_attachment_roots.<locals>.<genexpr>M  s\   é € ð 5Ñ2F¨$ØŸ™×)ô &Ü.0¯lªlÐ;VÐX\×XaÑXa×.bô &à˜[Õ(×1Ñ1×3ô &�˜×%Ò%Ó2Fùs   ‚A8Ÿ$A8ÁA8Á'A8)	rP   r‚  r¥   r‹   rb  rƒ  r„  Úextendr‰  )r¦   Úrootss     r   Ú_kanban_attachment_rootsr•  G  sp   € ä�z‰z�~‰~Ð>ÀÓC×IÑIÓK€HßÜ�X“×)Ñ)Ó+Ð,Ð,Ü‹^˜hÕ&¨Õ6Ð7€EØ	‡L�Lñ 5Ô2DÔ2Fó 5ô 5ð €Lr   c                ó:   € V ^8„  d   QhR\         \        ,          /# rj   ri  )r   s   "r   r   r   S  s   € ÷ :ñ :¤t¬D¥zñ :r   c                 óÄ   a€ ^ RI Hp  V3R lV ! 4       P                  \        P                  4       4       p. \        \        \        4      O\        4       O\        4       OVO# )zCReturn roots from which model-emitted local media may be delivered.)Úmedia_delivery_allow_dirsc              3   óô   <"  € T Fm  pVP                  R 4       FU  p\        \        P                  P	                  VP                  4       4      4      ;oP                  4       '       g   KQ  Sx € KW  	  Ko  	  R# 5i)Ú,N)Úsplitrb  rP   r6   rƒ  r‹   Úis_absolute)rì   r²  Úraw_rootÚroots   &  €r   rï   Ú0_media_delivery_allowed_roots.<locals>.<genexpr>V  s]   øé € ð OÙG�ØŸ™ CÖ(ˆHÜœŸ™×+Ñ+¨H¯N©NÓ,<Ó=Ó>Ð>ˆD×KÑK×M÷ 	ŠÙ(ñ 	ÓGùs   ƒA"A8Á*A8)
Úgateway.media_policyr˜  r›  rP   ÚpathsepÚmaprb  ÚMEDIA_DELIVERY_SAFE_ROOTSrt  r•  )r˜  Úoperator_rootsrž  s     @r   Ú_media_delivery_allowed_rootsr¥  S  s`   ø€ å>ôOÙ3Ó5×;Ñ;¼B¿J¹JÔGóO€Nð:ŒS”Ô0Ó1ð :Ô4HÓ4Jð :Ü%Ó'ð:Ø*8ð:ð :r   c                ó$   € V ^8„  d   QhR\         /# rj   ©Úfloat)r   s   "r   r   r   ^  s   € ÷ Xñ X¬ñ Xr   c                 óž   aa€ ^ RI Hp Hp V ! 4       '       g   R# V! 4       P                  4       o\	        \
        4      o\        VV3R lS4      # )zKRecency window (seconds) for trusting fresh files; 0 = pure-allowlist mode.)Úmedia_delivery_trust_recentÚ#media_delivery_trust_recent_secondsç        c                  óB   <€ S '       d   \        R \        S 4      4      # S# ©r¬  )Úmaxr¨  )Úcustomrv   s   €€r   rš  Ú1_media_delivery_recency_seconds.<locals>.<lambda>e  s   ø€ ¿&œs 3¬¨f«Ó6ÐMÀgÐMr   )r   rª  r«  r‹   r¨  Ú,_MEDIA_DELIVERY_TRUST_RECENT_DEFAULT_SECONDSrw   )rª  r«  r°  rv   s     @@r   Ú_media_delivery_recency_secondsr³  ^  s<   ù€ çeÙ&×(Ò(ÙÙ0Ó2×8Ñ8Ó:€FÜÔ@ÓA€GÜÕMÈwÓWÐWr   c                ó:   € V ^8„  d   QhR\         \        ,          /# rj   ri  )r   s   "r   r   r   h  s   € ÷ cñ c¤¤T¥
ñ cr   c                 óv   € \        4        U Uu. uF  p \        R4       F  qV,          NK  	  K  	  upp # u upp i )z«Named-board ``kanban.db`` stores (+ sidecars): they sit beside the ATTACHMENTS dir
``_kanban_attachment_roots`` allowlists and hold every task, comment and run transcript.rg  )r‰  rb  )ÚboardrF  s     r   Ú_kanban_board_db_pathsr·  h  s4   € ô '9Ô&:ÔbÑ&:˜UÄ}ÐU`ÖGa¸t�D�LˆLÑGa‰LÑ&:ÒbÐbùÓbs   Ž#5c                ó:   € V ^8„  d   QhR\         \        ,          /# rj   ri  )r   s   "r   r   r   n  s   € ÷ 'ñ '¤d¬4¥jñ 'r   c                 óÖ   a € \        \        P                  P                  R4      4      o . \	        \         \
        4      OV 3R l\         4       OR \        4        4       O\        4       O# )zEReturn absolute denylist paths under which delivery is never allowed.Ú~c              3   ó6   <"  € T F  pSV,          x € K  	  R # 5ir¼  rt   )rì   ÚsubÚhomes   & €r   rï   Ú/_media_delivery_denied_paths.<locals>.<genexpr>r  s   øé € ÐIÑ$H˜Sˆd�S�jŠjÓ$Hùs   ƒc              3   óL   "  € T F  p\          F  q!V,          x € K  	  K  	  R # 5ir¼  )Ú_ROOT_CREDENTIAL_PATHS)rì   ÚrÚrels   &  r   rï   r¾  s  s    é € ÐZÑ7˜!×CY¸C�#�gŠgÑCY‰gÓ7ùó   ‚"$)	rb  rP   r6   rƒ  r¢  Ú_MEDIA_DELIVERY_DENIED_PREFIXESÚ$_MEDIA_DELIVERY_DENIED_HOME_SUBPATHSr~  r·  )r½  s   @r   Ú_media_delivery_denied_pathsrÆ  n  sa   ø€ ä”—‘×"Ñ" 3Ó'Ó(€Dð'ŒS”Ô6Ó7ð 'ÜIÕ$HÓIð'áZÔ5Ô7ÓZð'ô $Ó%ð'ð 'r   ÚstrictÚexpandc          	      ó^   € V ^8„  d   QhR\         R\        R\        R\        \         ,          /# )r   r6   rÇ  rÈ  r   )rb  rµ   rf  )r   s   "r   r   r   w  s/   € ÷ ñ œð ¬ð ¼tð ÔPXÔY]ÕP^ñ r   c               ó’   €  V'       d   V P                  4       MT P                  VR7      #   \        \        \        3 d     R# i ; i)u·   ``path[.expanduser()].resolve(strict)`` or None when it fails (OSError / RuntimeError /
ValueError â€” embedded NUL, symlink loop, undeterminable home, missing file under ``strict``).©rÇ  N)rƒ  Úresolver^   ÚRuntimeErrorrñ   )r6   rÇ  rÈ  s   &$$r   Ú_resolve_pathrÎ  w  s?   € ðß%+�—‘Ô!°×>Ñ>ÀfÐ>ÓMÐMøÜ”\¤:Ð.ô Úðús   ‚, Š!, ¬AÁAc                ó0   € V ^8„  d   QhR\         R\        /# )r   rú   r   ©rb  rµ   )r   s   "r   r   r   €  s   € ÷ ñ ¬ð ´ñ r   c                ó  € \        \        \        P                  P	                  R4      4      4      p\        4        F@  p\        VRR7      pVf   K  W8H  ;'       g    \        W4      pV'       g   K7  W18w  g   K?   R# 	  R# )uh  True if ``resolved`` lives under a deny-listed system path â€” except a denied prefix that
IS the running user's own home: ``/root`` is listed so a non-root gateway can't deliver
another user's home, but a root-run gateway's own deliverables live under ``$HOME=/root``.
Credential sub-dirs (``~/.ssh``, ``~/.hermes/.env``) stay blocked (more-specific entries).rº  T©rÈ  F)rÎ  rb  rP   r6   rƒ  rÆ  Ú_path_is_within)rú   r½  ÚdeniedÚresolved_deniedÚhits   &    r   Ú_path_under_denied_prefixr×  €  sk   € ô
 œœbŸg™g×0Ñ0°Ó5Ó6Ó7€DÜ.Ö0ˆÜ'¨°tÔ<ˆØÒ"ÙØÑ)×WÐW¬_¸XÓ-Wˆß‰3�?Ö*Úñ 1ñ r   c                ó<   € V ^8„  d   QhR\         R\        R\        /# )r   rú   Úwindow_secondsr   )rb  r¨  rµ   )r   s   "r   r   r   �  s!   € ÷ ñ ¬ð ¼uð Ìñ r   c                ó¨   € V^ 8:  d   R#  \         P                   ! 4       V P                  4       P                  ,
          V8*  #   \         d     R# i ; i)u«   True if mtime is within ``window_seconds`` â€” a session-scoped trust signal: agents
produce artifacts seconds before sending; pre-existing host files are days/months old.F)r  r-  r.  r^   )rú   rÙ  s   &&r   Ú_file_is_recently_producedrÛ  �  sH   € ð ˜ÔÙðÜ—	’	“˜hŸm™m›o×6Ñ6Õ6¸>ÑIÐIøÜô Úðús   ‹6A ÁAÁAc                ó<   € V ^8„  d   QhR\         R\         R\        /# )r   r6   rž  r   rÐ  )r   s   "r   r   r   ›  s!   € ÷ ñ œ$ð ¤dð ¬tñ r   c                 ó¨   € \         P                  ! \        4      ;_uu_ 4        V P                  V4        R R R 4       R#   + '       g   i     R# ; i)NTF)r\   r]   rñ   Úrelative_to)r6   rž  s   &&r   rÓ  rÓ  ›  s8   € Ü	×	Ò	œZ×	(Õ	(Ø×Ñ˜ÔØ÷ 
)×	(×	(Ð	(ñ ús   £A Á A	rn   c                ó<   € V ^8„  d   QhR\         R\         R\         /# )r   rF  rv   r   rk   )r   s   "r   r   r   ¢  s!   € ÷ 'ñ '”ð 'œcð '¬3ñ 'r   c                ón   €  ^ RI Hp T! Y4      #   \         d    \        P                  ! Y4      u # i ; i)u  Scope-aware TERMINAL_* read: the per-turn scope carries the ACTIVE profile's settings while
os.getenv reads whatever a prior turn pinned into the process env. Only ImportError falls
back â€” a refusal scope must raise rather than rebuild another profile's policy from the env.)Úterminal_env)Útools.terminal_scoperá  r<  rP   Úgetenv)rF  rv   rá  s   && r   Ú_tenvrä  ¢  s7   € ð(Ý5ñ ˜Ó&Ð&øô ô (Ü�yŠy˜Ó'Ò'ð(ús   ‚ �!4³4c                ó\   € V ^8„  d   QhR\         \        \        \        3,          ,          /# rj   ©r$  r%  rb  )r   s   "r   r   r   ­  s!   € ÷ ñ ¤T¬%´´d°
Õ*;Õ%<ñ r   c                 ó  € \        RR4      P                  4       p  ^ RIpV '       d   VP                  V 4      M. p. p\        T\        4      '       d   TMR EF  p\        T\        4      '       d   TP                  4       MRpTP                  R\        P                  ! RT4      '       d   ^M^ 4      pT^ 8:  d   Kf  YV^,           R P                  R^4      ^ ,          p\        P                  P                  TRT 4      pTP                  R4      '       g!   \!        T4      ^8”  d   T^,          R8X  g   Ká  \#        \%        T4      4      ;p	f   Kû  TP'                  T	\%        T4      34       EK  	  T#   \         d    . u # i ; i)	z§Parse ``TERMINAL_DOCKER_VOLUMES`` (JSON list of ``host:container[:mode]``) into
``(host_path, container_path)``; named volumes / non-absolute hosts can't resolve here.ÚTERMINAL_DOCKER_VOLUMESrn   Nz:/z[A-Za-z]:[/\\]r  Ú/rt   )rä  r‹   ÚjsonÚloadsr[   r¤   r$  r8   Úfindr�  Úmatchr›  rP   r6   rƒ  r=  rÒ   rÎ  rb  r­  )
ÚrawÚ_jsonÚparsedÚmountsÚentryÚspecr  Úcontainer_rawÚhost_expandedÚ	host_paths
             r   Ú_parse_docker_volume_mountsr÷  ­  sK  € ô Ð)¨2Ó
.×
4Ñ
4Ó
6€CðÛß%(�—‘˜SÔ!¨bˆð ')€FÜ% f¬d×3Ò3‘¸Ó;ˆÜ *¨5´#× 6Ò 6ˆu�{‰{Œ}¸Bˆà�i‰i˜¤2§8¢8Ð,=¸t×#DÒ#D™aÈ!ÓLˆØ�!Œ8ÙØ 1�W˜X˜×,Ñ,¨S°!Ó4°QÕ7ˆäŸ™×*Ñ*¨4°°¨:Ó6ˆØ×(Ñ(¨×-Ò-´#°mÓ2DÀqÔ2HÈ]Ð[\ÕM]ÐadÔMdÙÜ&¤t¨MÓ':Ó;Ð;ˆIÔHØ�M‰M˜9¤d¨=Ó&9Ð:×;ñ <ð €Møô! ô ØŠ	ðús   œE5 Å5FÆFc                óF   € V ^8„  d   QhR\         R\        \         ,          /# ©r   Úsession_keyr   ©r8   r$  )r   s   "r   r   r   Ç  s   € ÷ ñ ´ð ¼TÄ#½Yñ r   c                ó¶  €  ^ RI Hp  ^ RIHp T! 4       ;'       g    Rp. p\        RR4      P                  4       ;p'       d   TP                  T! RT 24      4       TR8w  d   TP                  T! RT 24      4       TP                  R4       T '       d   TP                  T! RT  24      4       T#   \         d    R.u # i ; i  \         d    Rp L·i ; i)	u`  Candidate host sandbox dir names for the delivering session, best first. Mirrors
``_resolve_container_task_id`` (tools/terminal_tool.py): containers are PROFILE-scoped
(``default``, else ``profile:<name>``); legacy ``session:<key>`` sandboxes stay as a fallback.
The key is passed explicitly because delivery runs after the turn's contextvars were cleared.

Takes the key explicitly because the delivery pipeline runs after ``_handle_message_with_agent`` cleared
the turn's session contextvars (#93950) â€” an ambient lookup here would silently collapse onto
``default`` and miss the session's real sandbox.
)Úsanitize_task_id_for_pathrv   )Úget_active_profile_nameÚ$TERMINAL_DOCKER_SHARED_CONTAINER_KEYrn   zshared:zprofile:zsession:)Útools.environments.path_utilsrý  r[   Úhermes_cli.profilesrþ  rä  r‹   r­  )rú  rý  rþ  r‰   Ú
candidatesÚshareds   &     r   Ú_docker_sandbox_dir_candidatesr  Ç  sã   € ðÝKðÝ?Ù)Ó+×8Ð8¨yˆð €JäÐ=¸rÓB×HÑHÓJÐJ€vÖJØ×ÑÑ3°g¸f¸XÐ4FÓGÔHØ�)ÔØ×ÑÑ3°h¸w¸iÐ4HÓIÔJØ×Ñ�iÔ ßØ×ÑÑ3°h¸{¸mÐ4LÓMÔNØÐøô! ô Øˆ{Òðûô
 ô ØŠðús'   ‚B4 ‰C �C Â4CÃCÃCÃCc                ó$   € V ^8„  d   QhR\         /# rj   rO  )r   s   "r   r   r   é  s   € ÷ Añ AœDñ Ar   c                  óX   € \        R R4      P                  4       P                  4       R8H  # )ÚTERMINAL_ENVrn   Údocker)rä  r‹   rp   rt   r   r   Ú_docker_env_activer	  é  s&   € Ü� Ó$×*Ñ*Ó,×2Ñ2Ó4¸Ñ@Ð@r   c                ó$   € V ^8„  d   QhR\         /# rj   rO  )r   s   "r   r   r   í  s   € ÷ nñ n¤4ñ nr   c                 ó„   € \        4       ;'       d0    \        RR4      P                  4       P                  4       \        9   # )z@Docker backend with persistent containers (the default) enabled.ÚTERMINAL_CONTAINER_PERSISTENTÚtrue)r	  rä  r‹   rp   Ú_TRUTHYrt   r   r   Ú_docker_persistent_activer  í  s3   € äÓ×mÐm¤EÐ*IÈ6Ó$R×$XÑ$XÓ$Z×$`Ñ$`Ó$bÔfmÑ$mÐmr   c                óR   € V ^8„  d   QhR\         R\         R\        \        ,          /# )r   rú  Úleafr   ©r8   r$  rb  )r   s   "r   r   r   ò  s%   € ÷ ñ ´#ð ¼Sð ÄTÌ$ÅZñ r   c                ó$  € \        4       '       g   . #  ^ RIHp V! 4       R,          p\        V 4       Uu. uF<  pW4,          V,          P	                  RR7      ;pP                  4       '       g   K:  VNK>  	  up# u upi   \         d    . u # i ; i)z£Existing ``<sandbox>/docker/<candidate>/<leaf>`` host dirs in candidate order;
the translator tries each until the file resolves. Empty unless Docker + persistent.)Úget_sandbox_dirr  FrË  )r  Útools.environments.baser  r  rÌ  ry  r[   )rú  r  r  ÚbaserF  Úcands   &&    r   Ú _docker_persistent_sandbox_rootsr  ò  s‘   € ô %×&Ò&Øˆ	ðÝ;ÙÓ  8Õ+ˆÜ!?ÀÔ!Ló RÑ!L˜Ø!�[¨4Õ/×8Ñ8ÀÐ8ÓFÐF�D×NÑN×P÷ �Ñ!Lñ Rð 	Rùò Røäô ØŠ	ðús(   ”!A? µ7A:Á1A:Á7A? Á:A? Á?BÂBc                óF   € V ^8„  d   QhR\         R\        \        ,          /# rù  r  )r   s   "r   r   r      s"   € ÷ Fñ F´cð FÄ4ÌÅ:ñ Fr   c                óÔ  € \        4       '       g   . # \        RR4      P                  4       P                  4       \        9   d}   \        R4      ;'       g    \
        P                  ! 4       p \        \
        P                  P                  V4      4      P                  RR7      pTP                  4       '       d   T.# . # \        V R4      #   \        \        \        3 d    . u # i ; i)z�Existing host candidates for ``/workspace``: the explicit cwd mount
(``TERMINAL_DOCKER_MOUNT_CWD_TO_WORKSPACE``) if set, else the persistent sandbox layouts.Ú&TERMINAL_DOCKER_MOUNT_CWD_TO_WORKSPACErV  ÚTERMINAL_CWDFrË  Ú	workspace)r  rä  r‹   rp   r  rP   Úgetcwdrb  r6   rƒ  rÌ  r^   rÍ  rñ   ry  r  )rú  Úcwdrã   s   &  r   Ú$_default_docker_workspace_host_rootsr      s¼   € ô %×&Ò&Øˆ	ÜÐ5°wÓ?×EÑEÓG×MÑMÓOÔSZÔZÜ�NÓ#×2Ð2¤r§y¢y£{ˆð	ÜœŸ™×*Ñ*¨3Ó/Ó0×8Ñ8ÀÐ8ÓFˆDð Ÿ™Ÿš�ˆvÐ.¨BÐ.Ü+¨K¸ÓEÐEøô œ¤zÐ2ô 	ØŠIð	ús   Á-8C ÃC'Ã&C'c                ó\   € V ^8„  d   QhR\         \        \        \        3,          ,          /# rj   ræ  )r   s   "r   r   r     s!   € ÷ 	ñ 	¤T¬%´´d°
Õ*;Õ%<ñ 	r   c                 óÖ   € \        4       '       g   . #  ^ RIHp  V ! 4        Uu. uF'  p\        VR,          4      \        VR,          4      3NK)  	  up# u upi   \         d    . u # i ; i)z²(host, container) pairs for the auto-mounted Hermes cache dirs (``/root/.hermes/...`` in
MEDIA tags); longer prefixes than the ``/root`` home mount, so longest-prefix match wins.)Úget_cache_directory_mountsrö  Úcontainer_path)r	  Útools.credential_filesr#  rb  r[   )r#  Úms     r   Ú_cache_dir_container_mountsr'    sd   € ô ×ÒØˆ	ðÝEÙKeÔKgÓhÑKgÀa”�a˜•nÓ%¤t¨AÐ.>Õ,?Ó'@ÓAÑKgÑhÐhùÒhøÜô ØŠ	ðús"   ”A £-AÁA ÁA ÁA(Á'A(c          
      óL   € V ^8„  d   QhR\         R\        R\        R\        RR/# )r   Ú	candidaterú  ÚreasonÚquietr   N)rb  r8   rµ   )r   s   "r   r   r     s8   € ÷ Jñ J¬Tð JÄð JÌSð JÔY]ð JÐjnñ Jr   c                ó´   € V'       g   \        4       '       g   R# \        P                  R\        \	        V 4      4      TV'       d   RV 24       R# R4       R# )a  Name WHY a container-absolute MEDIA path failed translation (otherwise the only signal is
the generic "Skipping unsafe MEDIA directive path" line). Docker-only; host rejections and ``quiet``
callers (fs routes, which also see ordinary host paths) stay silent.

See #93950.
Nz�Docker MEDIA path %s did not resolve to a host sandbox file (%s%s); the producing container's sandbox directory may not exist yet or was prunedz, session_key=rn   )r	  r   rX   Ú_log_safe_pathr8   )r)  rú  r*  r+  s   &&&&r   Ú_warn_unresolved_docker_mediar.    sL   € ÷ Ô&×(Ò(ÙÜ
‡N�Nð  ä!/´°I³Ó!?Àß5@�^ K =Ð1öJð GIöJr   r+  c          	      ó^   € V ^8„  d   QhR\         R\        R\        R\        \         ,          /# )r   r)  rú  r+  r   )rb  r8   rµ   rf  )r   s   "r   r   r   *  s0   € ÷ &ñ &´dð &Ìð &Ô]að &ÔnvÔw{Õn|ñ &r   c          
     ó’  € V P                  4       P                  R4      '       g   R# \        P                  ! \        4      ;_uu_ 4        ^ RIHp V! 4        RRR4       . \        4       O\        4       OpV UUu0 uF  w  rVVP                  4       kK  	  pppRV9  d"   VP                  R \        V4       4       4       RV9  dH   V P                  4       P                  R4      '       g#   VP                  R \        VR	4       4       4       V'       g   \        WR
V4       R# V P                  4       pV U	U
Uu. uFa  w  ršV
P                  4       P                  R4      ;'       g    RpW‹8X  g!   VP                  VR,           4      '       g   KT  Wš\        V4      3NKc  	  pp
p	pV'       g   \        WRV4       R# \        VR R7       FI  w  ršp\!        W�P#                  V
4      ,          RR7      pVf   K.  Wé8X  g   \%        Wé4      '       g   KG  Vu # 	  \        WRV4       R#   + '       g   i     ELÙ; iu uppi u upp
p	i )z´Container-absolute path -> host path via longest-prefix match over ``docker_volumes``, the
auto-mounted cache dirs (``/root/.hermes/...``), persistent ``/workspace`` and ``/root``.ré  N)Ú_ensure_terminal_env_bridgedú
/workspacec              3   ó:   "  € T F  q\        R 4      3x € K  	  R# 5i)r2  Nra  ©rì   rž  s   & r   rï   Ú9_translate_docker_container_media_path.<locals>.<genexpr>8  s   é € ÐoÑ=n°TœT ,Ó/Õ0Ó=nùrr  ú/rootz/root/.hermesc              3   ó:   "  € T F  q\        R 4      3x € K  	  R# 5i)r6  Nra  r4  s   & r   rï   r5  =  s   é € ð eÙ.c d”4˜“=Õ!Ó.cùrr  r½  zno sandbox mounts resolvedzno mounted prefix matchesc                 ó   € V ^,          ) # )r   rt   )r&  s   &r   rš  Ú8_translate_docker_container_media_path.<locals>.<lambda>J  s
   € ÈAÈaÍDÉ5r   )r  TrË  zhost file missing from sandbox)Úas_posixr=  r\   r]   r[   Útools.terminal_toolr1  r÷  r'  r“  r   r  r.  ÚrstriprÒ   ÚsortedrÎ  rÞ  rÓ  )r)  rú  r+  r1  rñ  rí   ÚcÚmountedÚcandidate_posixÚ	host_rootÚcontainer_rootr=   ÚmatchedÚ_scoreÚ
translateds   &&$            r   Ú&_translate_docker_container_media_pathrF  *  sõ  € ð ×ÑÓ×*Ñ*¨3×/Ò/Ùô 
×	Ò	œY×	'Õ	'ÝDÙ$Ô&÷ 
(ð NÔ*Ó,ÐMÔ/JÓ/LÐM€FÙ(.Ô/©¡ ˆq�z‰zŽ|©€GÑ/à˜7Ô"Ø�‰ÑoÔ=aÐbmÔ=nÓoÔoð �gÔ i×&8Ñ&8Ó&:×&EÑ&EÀo×&VÒ&VØ�‰ñ eÜ.NÈ{Ð\bÔ.cóeô 	eçÜ% iÐ>ZÐ\aÔbÙà×(Ñ(Ó*€OÙY_õ YÑY_Ñ<U¸IØ,×5Ñ5Ó7×>Ñ>¸sÓC×JÐJÀs�6Ø!Ô+¨×/IÑ/IÈ&ÐSVÍ,×/Wô 8�	¬3¨v«;Ó7ÑY_€Gò Y÷ Ü% iÐ>YÐ[`ÔaÙÜ-3°GÁ×-QÑ)ˆ	 6Ü" 9×/DÑ/DÀ^Ó/TÕ#TÐ]aÔbˆ
ØÔ!ØÔ'¬?¸:×+QÔ+QØÒñ	 .Rô
 " )Ð:ZÐ\aÔbÙ÷? 
(×	'Ð	'üó 0ùôYs$   Á
H(Á;H<Ä<,IÅ)$IÆIÈ(H9	c                óR   € V ^8„  d   QhR\         R\         R\        \         ,          /# ©r   r6   rú  r   ©r8   rf  )r   s   "r   r   r   S  s%   € ÷ $ñ $¤sð $¼ð $ÄhÌsÅmñ $r   c                óÀ  € \        V 4      pV'       g   R#  \        \        P                  P	                  V4      4      pTP                  4       '       g   R# \        Y1R7      pTf   \        TRR7      pTe   TP                  4       '       g   R# \        4        F4  p\        TRR7      pTf   K  \        YF4      '       g   K)  \        T4      u # 	  ^ RIHp T! 4       '       g   \#        T4      '       d   R# \        T4      # \%        4       pT^ 8”  d.   \#        T4      '       g   \'        YH4      '       d   \        T4      # R#   \
        \        \        3 d     R# i ; i)aº  Safe absolute file path for native media delivery, else None. Default: any existing
regular file outside the credential / system denylist (symmetric with inbound). Strict
(``HERMES_MEDIA_DELIVERY_STRICT=1``, public bots where prompt injection must not exfiltrate
host secrets): MUST be under a Hermes cache, an operator root (``HERMES_MEDIA_ALLOW_DIRS``),
or freshly produced within the recency window. Symlinks are resolved before any check.N©rú  TrË  rÒ  )Úmedia_delivery_strict)Ú_normalize_media_tag_pathrb  rP   r6   rƒ  r^   rÍ  rñ   rœ  rF  rÎ  r,  r¥  rÓ  r8   r   rL  r×  r³  rÛ  )	r6   rú  r)  Úexpandedrú   rž  Úresolved_rootrL  Úwindows	   &&       r   Úvalidate_media_delivery_pathrQ  S  s   € ô *¨$Ó/€IßÙðÜœŸ™×*Ñ*¨9Ó5Ó6ˆð ×Ñ×!Ò!Ùä5°hÔX€HØÒÜ  °$Ô7ˆØÒ˜x×/Ñ/×1Ò1Ùä-Ö/ˆÜ% d°4Ô8ˆØÔ$¬¸×)QÔ)QÜ�x“=Ò ñ 0õ
 ;Ù ×"Ò"Ü0°×:Ò:ˆtÐMÄÀHÃÐMä,Ó.€FØ�Œ
Ô4°X×>Ò>Ü*¨8×<Ò<Ü�8‹}ÐÙøô3 ”\¤:Ð.ô âðús   —(E ÅEÅEz[\x00-\x1f\x7f\x85\u2028\u2029]c                ó0   € V ^8„  d   QhR\         R\         /# ©r   r6   r   rk   )r   s   "r   r   r     s   € ÷ 7ñ 7œð 7¤ñ 7r   c                óN   € \         P                  R\        V 4      4      R,          # )z9Return a single-line, length-bounded path for log output.Ú?:NéÈ   N)Ú_LOG_UNSAFE_CHARSr¼  r8   ©r6   s   &r   r-  r-    s   € ä× Ñ  ¤c¨$£iÓ0°Õ6Ð6r   c          	      óŠ   € V ^8„  d   QhR\         R\         R\        \        \        ,          ,          R\        \         ,          /# )r   rú  ÚlabelÚdroppedr   )r8   rf  r$  r|   )r   s   "r   r   r   „  s7   € ÷ ñ ´Cð Äð Ü&.¬t´D­zÕ&:ðÜFNÌsÅmñr   c                ó  € \        V 4      p\        WAR7      pV'       g   ^ RIHp V! V4      pV'       gO   \	        V4      '       g   RMRp\
        P                  RW'\        V4      4       Ve   VP                  RVRV/4       V# )a_  ``validate_media_delivery_path`` plus the shared "Skipping unsafe ..." warning. A path the
host cannot see is retried against the active remote sandbox (ssh/modal/...; #466). When
``dropped`` is a list, a rejected path is appended as ``{"path", "reason"}`` so the caller can
report the drop instead of booking a delivery that never happened (#115908).rK  )Úfetch_remote_mediaznot found on this hostzdenied by the delivery policyzSkipping %s (%s): %sr6   r*  )	r8   rQ  Úgateway.media_fetchr]  Ú_existing_regular_filer   rX   r-  r­  )Úraw_pathrú  rZ  r[  rî  Ú	safe_pathr]  r*  s   &&&&    r   Ú_validated_delivery_pathrb  „  sw   € ô ˆh‹-€CÜ,¨SÔJ€IßÝ:Ù& sÓ+ˆ	ßô 2HÈ×1LÒ1LÑ)ÐRqˆÜ�‰Ð-¨u¼nÈSÓ>QÔRØÒØ�N‰N˜F C¨°6Ð:Ô;ØÐr   c                ó0   € V ^8„  d   QhR\         R\        /# ©r   rî  r   r´   )r   s   "r   r   r   ™  s   € ÷ ñ ¤ð ¬ñ r   c                 óª   €  \        \        P                  P                  V 4      4      P	                  4       #   \
        \        \        3 d     R # i ; i©F)rb  rP   r6   rƒ  r,  r^   rÍ  rñ   )rî  s   &r   r_  r_  ™  sC   € ðÜ”B—G‘G×&Ñ& sÓ+Ó,×4Ñ4Ó6Ð6øÜ”\¤:Ð.ô Úðús   ‚58 ¸AÁAú.pdfzapplication/pdfú.mdztext/markdownú.txtz
text/plainú.csvztext/csvz.logú.jsonzapplication/jsonú.xmlzapplication/xmlú.yamlzapplication/yamlú.ymlz.tomlzapplication/tomlz.iniz.cfgú.zipzapplication/zipú.doczapplication/mswordú.xlszapplication/vnd.ms-excelú.pptzapplication/vnd.ms-powerpointú.docxzGapplication/vnd.openxmlformats-officedocument.wordprocessingml.documentú.xlsxzAapplication/vnd.openxmlformats-officedocument.spreadsheetml.sheetú.pptxzIapplication/vnd.openxmlformats-officedocument.presentationml.presentationz.tsz.pyz.shz	.markdownú.tsvz.jsonlz.ndjsonz.confz.propertiesú.htmlú.htmz.cssz.scssz.sassz.lessz.pyiz.jsz.mjsz.cjsz.tsxz.jsxz.bashz.zshz.fishz.ps1z.batz.cz.hz.cppz.ccz.hppz.csz.javaz.ktz.goz.rsz.rbz.phpz.plz.luaz.rz.jlz.swiftz.mz.scalaz.cljz.exz.exsz.erlz.sqlz.graphqlz.protoz.tfz.hclz.dockerfilez	.makefilez.cmakez.gradlez.rstz.texz.srtz.vttz.diffz.patchz
image/jpegz	image/pngz
image/webpz	image/gifÚ|c              #   óB   "  € T F  qP                  R 4      x € K  	  R# 5i©rÃ   N©Úlstrip©rì   Úes   & r   rï   rï   Ø  s   é € Ð)UÑAT¸A¯(©(°3¯-¨-ÓATùó   ‚T)r  Úreverseu9   ï¼ˆï¼‰ã€ˆã€‰ã€Šã€‹ï¼šï¼Œã€‚ï¼›ï¼�ï¼Ÿã€�â€œâ€�â€˜â€™ã€�ã€‘zq[`"'*_]{0,3}MEDIA:\s*(?P<path>`[^`\n]+?`|"[^"\n]+?"|'[^'\n]+?'|(?:~/|/|[A-Za-z]:[/\\])\S+?(?:[^\S\n]+\S+?)*?\.(?:z))(?=[\s`"'*_,;:)\]}\[z%]|MEDIA:|\.(?:\s|$)|$)[`"'*_]{0,3}\.?zp[`"'*_]{0,3}MEDIA:\s*(?P<path>`[^`\n]+`|"[^"\n]+"|'[^'\n]+'|(?:~/|/|[A-Za-z]:[/\\])[^\s\n`"']+?)(?=[`"'\s,;:)\]}z]|MEDIA:|$)[`"'*_]{0,3}\s*c          	      óˆ   € V ^8„  d   QhR\         R\        P                  R\        \        \         \
        3,          ,          /# )r   Ú	scan_textrí  r   )r8   r�  ÚMatchrf  r%  r9   )r   s   "r   r   r     s5   € ÷  ñ  ¬ð  ´R·X±Xð  Ä(Ì5ÔQTÔVYÐQYÍ?ÕB[ñ  r   c                óN  € \        VP                  R4      4      pV'       g   R# \        V4      pV'       d   W1P                  R4      3# VP	                  R4      pWR P                  R^4      ^ ,          pVP                  R^4      pVR8w  d   VRV pVP                  R4      V,
          p\        ^4       Fj  p\        P                  ! RWWR 4      p	V	'       g    R# WyP                  4       ,           p
\        \        VRV
 4      4      pV'       d   W4V
,           3u # T
pKl  	  R# )aj  Extensionless MEDIA tag match -> validated on-disk ``(safe_path, end_offset)`` or None: the
captured path first, then extended across single spaces (max 8 tokens, never past a newline
or the next ``MEDIA:``).

When that fails validation, the candidate is progressively extended forward across single spaces
(validation-gated, bounded at 8 tokens, never past a newline or a subsequent ``MEDIA:`` keyword) so
unknown-extension paths containing spaces deliver (#24032). Returns ``(safe_path, end_offset)`` where
``end_offset`` is the index in ``scan_text`` just past the matched path, or ``None`` when nothing
validates.
r6   NÚ
úMEDIA:z[ \t]*[^ \t]+éÿÿÿÿ)
rM  ÚgrouprQ  ÚendÚstartr›  rì  r  r�  rí  )rƒ  rí  r6   Úsafer‹  ÚsegmentÚnxtÚposrí   ÚtokenÚtok_ends   &&         r   Ú_match_extensionless_pathr’    s
  € ô % U§[¡[°Ó%8Ó9€DßÙÜ'¨Ó-€DßØ—Y‘Y˜vÓ&Ð&Ð&Ø�K‰K˜Ó€EØ˜Ð×%Ñ% d¨AÓ.¨qÕ1€GØ
�,‰,�x Ó
#€CØ
ˆb„yØ˜$˜3�-ˆØ
�)‰)�FÓ
˜eÕ
#€CÜ�1ŽXˆÜ—’Ð)¨7°4¨=Ó9ˆßØñ ð Ÿ	™	›Õ#ˆÜ+Ô,EÀgÈhÈwÐFWÓ,XÓYˆßØ �Ð(Ò(ØŠñ ñ r   c                ó0   € V ^8„  d   QhR\         R\         /# rd  rk   )r   s   "r   r   r   ;  s   € ÷ 5ñ 5¤3ð 5¬3ñ 5r   c                 ó  € \        T ;'       g    R 4      P                  4       p\        V4      ^8¼  d7   V^ ,          VR,          8X  d"   V^ ,          R9   d   V^R P                  4       pVP                  R4      P	                  R4      # )rn   z`"'z
`"',.;:)}]rˆ  )r8   r‹   rÒ   r}  r<  )rî  r6   s   & r   rM  rM  ;  sm   € Üˆs�yˆy�b‹>×ÑÓ!€DÜ
ˆ4ƒy�A„~˜$˜q�' T¨"¥XÔ-°$°qµ'¸VÔ2CØ�A�bˆz×ÑÓ!ˆØ�;‰;�vÓ×%Ñ% mÓ4Ð4r   c                ó0   € V ^8„  d   QhR\         R\        /# rS  r´   )r   s   "r   r   r   B  s   € ÷ 	@ñ 	@¬Cð 	@´Dñ 	@r   c                óV   € \        V 4      P                  P                  4       \        9  # )u+  True when ``path`` has no extension or one outside MEDIA_DELIVERY_EXTS â€” such paths
take the validated delivery pass so nonexistent / denylisted ones stay visible.

``path`` â€” either the basename has no extension at all (Caddyfile, Makefile, â€¦) or the extension is not
in MEDIA_DELIVERY_EXTS (.py, .log, .weirdext, â€¦). Such paths route through the validated delivery pass
(``validate_media_delivery_path``) instead of the unconditional one, so every file type is deliverable
(#36060) while nonexistent / denylisted paths stay visible in the text.
)rb  r>   rp   ÚMEDIA_DELIVERY_EXTSrX  s   &r   Ú!_path_lacks_deliverable_extensionr˜  B  s#   € ô �‹:×Ñ×"Ñ"Ó$Ô,?Ñ?Ð?r   c                ó0   € V ^8„  d   QhR\         R\        /# ©r   r   r   r´   )r   s   "r   r   r   N  s   € ÷ Yñ Y¤ð Y¬ñ Yr   c                 ó@   € R V 9   ;'       g    RV 9   ;'       g    RV 9   # )r‡  ú[[audio_as_voice]]ú[[as_document]]rt   ©r   s   &r   Ú_has_media_directivesrŸ  N  s*   € Ø�tÑ×XÐXÐ3°tÑ;×XÐXÐ?PÐTXÑ?XÐXr   z<|eos|>c                ó0   € V ^8„  d   QhR\         R\        /# rš  r7   )r   s   "r   r   r   Z  s   € ÷ (ñ (¤3ð (¬3ñ (r   c                óä   € \        V P                  4       4      ;rV\        \        4      8¼  d:   W\        \        4      ,
          V \        8X  d   V\        \        4      ,          pKM  W!8  d   V# R# )z˜Offset where the run of exact ``<|eos|>`` tokens closing ``text`` (trailing whitespace
ignored) begins, else -1; the run ends at ``len(text.rstrip())``.rˆ  )rÒ   r<  Ú_TERMINAL_SENTINEL)r   rŠ  r‹  s   &  r   Ú_terminal_sentinel_startr£  Z  s]   € ô �d—k‘k“mÓ$Ð$€CØ
”3Ô)Ó*Ô
*¨t¼CÔ@RÓ<SÕ4SÐTYÐ/ZÔ^pÔ/pØ”Ô'Ó(Õ(ŠØ”Kˆ5Ð' RÐ'r   c                ó0   € V ^8„  d   QhR\         R\         /# rš  rk   )r   s   "r   r   r   c  s   € ÷ 	ñ 	¤ð 	¬ñ 	r   c                óÀ   € \         pVP                  VP                  V 4      4      p\        V 4      pV^ 8¼  d&   \	        W#\        V P                  4       4      3.4      pV# )zøOffset-preserving mask of protected spans (code, quotes, JSON string values) and of a
terminal ``<|eos|>`` sentinel, so a tag glued to it ends on whitespace like any other.
BasePlatformAdapter is defined later in this module; resolved at call time.)ÚBasePlatformAdapterÚ_mask_json_string_mediaÚ_mask_protected_spansr£  Ú_blank_spansrÒ   r<  )r   ÚAÚmaskedr‹  s   &   r   Ú_mask_media_scan_textr¬  c  sW   € ô 	€AØ×&Ñ& q×'>Ñ'>¸tÓ'DÓE€FÜ$ TÓ*€EØ�„zÜ˜f¬s°4·;±;³=Ó/AÐ'BÐ&CÓDˆØ€Mr   c                ó0   € V ^8„  d   QhR\         R\        /# rš  rû  )r   s   "r   r   r   o  s   € ÷ ñ ¤ð ¬ñ r   c                ó¶   € \        \        V 4      4      p\        V 4      pV'       d2   V^ 8¼  d+   VP                  V\	        V P                  4       4      34       V# )z­Spans to delete from ``text``: its deliverable MEDIA tags (located on the masked copy)
plus a terminal ``<|eos|>`` sentinel, which is a control token and never user content.)Ú_real_media_tag_spansr¬  r£  r­  rÒ   r<  )r   Úspansr‹  s   &  r   Ú_deliverable_tag_spansr±  o  sH   € ô "Ô"7¸Ó"=Ó>€EÜ$ TÓ*€Eß�˜!”Ø�‰�eœS §¡£Ó/Ð0Ô1Ø€Lr   c                ó$   € V ^8„  d   QhR\         /# )r   r«  rk   )r   s   "r   r   r   y  s   € ÷ 6ñ 6¬ñ 6r   c              #  óþ   "  € \         P                  V 4       F_  p\        VP                  R4      4      pV'       g   K'  \	        V4      '       g   K:  \        W4      pVf   KK  W^ ,          V^,          3x € Ka  	  R# 5i)zœYield ``(match, safe_path, end_offset)`` for every extension-less / unknown-extension
MEDIA tag in ``masked`` that ``validate_media_delivery_path`` accepts.r6   N)ÚMEDIA_EXTENSIONLESS_TAG_REÚfinditerrM  r‰  r˜  r’  )r«  rí  r6   rú   s   &   r   Ú_extensionless_media_matchesr¶  y  sb   é € ô ,×4Ñ4°VÖ<ˆÜ(¨¯©°VÓ)<Ó=ˆß‰4Ô5°d×;Ô;Ü0°Ó?ˆHØÔ#Ø a�[¨(°1­+Ð5Ô5ó =ùs   ‚8A=¿A=ÁA=Á#A=c                ó0   € V ^8„  d   QhR\         R\        /# )r   r«  r   rû  )r   s   "r   r   r   „  s   € ÷ ñ ¤#ð ¬$ñ r   c                ó´   € \         P                  V 4       Uu. uF  qP                  4       NK  	  ppVP                  R \	        V 4       4       4       V# u upi )z°(start, end) spans of deliverable MEDIA tags on a masked copy: known-extension tags
unconditionally, extension-less / unknown ones only if validate_media_delivery_path accepts.c              3   óJ   "  € T F  w  rq1P                  4       V3x € K  	  R # 5ir¼  ©r‹  )rì   rí  rí   rŠ  s   &   r   rï   Ú(_real_media_tag_spans.<locals>.<genexpr>ˆ  s   é € Ð`Ñ;_©-¨%°C—+‘+“- Õ%Ó;_ùr_  )ÚMEDIA_TAG_CLEANUP_RErµ  Úspanr“  r¶  )r«  r&  r°  s   &  r   r¯  r¯  „  sM   € ô &:×%BÑ%BÀ6Ô%JÓKÑ%J —6‘6–8Ñ%J€EÐKØ	‡L�LÑ`Ô;WÐX^Ô;_Ó`Ô`Ø€Lùò Ls   ˜Az```[^\n]*\n.*?```z	`[^`\n]+`c                ó0   € V ^8„  d   QhR\         R\        /# ©r   r  r   rû  )r   s   "r   r   r   �  s   € ÷ añ aœð a¤ñ ar   c                ó’   € \         \        3 UUu. uF)  qP                  V 4       F  q"P                  4       NK  	  K+  	  upp# u uppi )zH(start, end) spans of fenced code blocks and inline code in ``content``.)Ú_FENCED_CODE_REÚ_INLINE_CODE_RErµ  r½  )r  Úrxr&  s   &  r   Ú_code_spansrÄ  �  s6   € ä /´ÑAÔ`ÑA˜Ï;É;ÐW^ÖK_Àa�F‰FŽHÑK_‰HÑAÒ`Ð`ùÓ`s   �/Ac                ó<   € V ^8„  d   QhR\         R\        R\         /# ©r   r   r°  r   rû  )r   s   "r   r   r   •  s!   € ÷ ñ ”sð ¤4ð ¬Cñ r   c                ó–   € \        V 4      pV F#  w  r4W#V  Uu. uF  qUR8X  d   TMRNK  	  upW#V% K%  	  RP                  V4      # u upi )zQReplace every non-newline char inside ``spans`` with a space (offsets preserved).r†  Ú rn   )r$  rÆ   )r   r°  Úcharsr‹  rŠ  r>  s   &&    r   r©  r©  •  sT   € ä�‹J€EÛ‰
ˆØ=BÈÑ=MÓNÑ=M¸ d¤™A°Ò3Ñ=MÑNˆ�CÒñ à�7‰7�5‹>Ðùò Os   ™Ac                ó<   € V ^8„  d   QhR\         R\        R\         /# rÆ  rû  )r   s   "r   r   r   �  s!   € ÷ ñ œð ¤Dð ¬Sñ r   c                ód  € V'       g   V # . p\        V4       Fb  w  r4V'       dD   W2R,          ^,          8:  d0   VR,          ^ ,          \        VR,          ^,          V4      3VR&   KP  VP                  W434       Kd  	  \        V 4      p\	        V4       F	  w  rgWVV1 K  	  RP                  V4      # )z“Delete ``spans`` from ``text``, merging overlapping/nested ones first so multi-pattern
matches over the same tag never double-delete adjacent text.rn   rˆ  )r=  r¯  r­  r$  ÚreversedrÆ   )r   r°  ÚmergedrÐ   r  rÉ  r‹  rŠ  s   &&      r   Ú_delete_spansrÎ  �  s˜   € ÷ ØˆØ€FÜ�u–‰ˆß�a "�: a�=Ô(Ø  �* Q�-¬¨V°B­Z¸­]¸AÓ)>Ð?ˆF�2‹Jà�M‰M˜1˜&Ö!ñ	 ô
 �‹J€EÜ˜vÖ&‰
ˆØ˜�)Òñ 'à�7‰7�5‹>Ðr   c                ó0   € V ^8„  d   QhR\         R\         /# rš  rk   )r   s   "r   r   r   ®  s   € ÷ Cñ C¤cð C¬cñ Cr   c                ó¦   € V '       d   \        V 4      '       g   V # V P                  RR4      P                  RR4      p\        V\        V4      4      # )uL  Remove MEDIA: tags and [[audio_as_voice]] / [[as_document]] markers so they never render
as text (backstop after ``extract_media``). Protected spans are mask-located only â€” tags
inside them are neither stripped nor mangled, matching ``extract_media`` so display and
delivery agree. Empty/None text is returned as-is.

See #16434.
rœ  rn   r�  )rŸ  rI   rÎ  r±  )r   Úcleaneds   & r   Ú_strip_media_tag_directivesrÒ  ®  sJ   € ÷ Ô,¨T×2Ò2ØˆØ�l‰lÐ/°Ó4×<Ñ<Ð=NÐPRÓS€GÜ˜Ô"8¸Ó"AÓBÐBr   c                ó<   € V ^8„  d   QhR\         R\        R\        /# ©r   rÓ  Úfilenamer   rô  )r   s   "r   r   r   ¼  s!   € ÷ ñ ¤Eð ´Sð ¼Sñ r   c                óÔ  € \        4       pV'       d   \        V4      P                  MRP                  RR4      P	                  4       pV'       d   VR9   d   RpVR\
        P                  ! 4       P                  R,           RV 2,          pVP                  4       P                  VP                  4       4      '       g   \        RV: 24      hVP                  V 4       \        V4      # )	z«Save raw document bytes to the cache as ``doc_{uuid12}_{original_name}`` and return
the absolute path; raises ValueError if the sanitized path escapes the cache directory.rL  Ú rn   Údoc_rÁ   rí   zPath traversal rejected: >   rÃ   ú..)Úget_document_cache_dirrb  rF  rI   r‹   rÈ   rÉ   rÊ   rÌ  Úis_relative_torñ   rì  r8   )rÓ  rÕ  rÝ  Ú	safe_namerï  s   &&   r   Úcache_document_from_bytesrÝ  ¼  s¼   € ô 'Ó(€Iç(0”�h“×$Ò$°j×IÑIÈ&ÐRTÓU×[Ñ[Ó]€Iß˜	 [Ô0Øˆ	Ø˜T¤$§*¢*£,×"2Ñ"2°3Õ"7Ð!8¸¸)¸ÐEÕE€Hà×ÑÓ×,Ñ,¨Y×->Ñ->Ó-@×AÒAÜÐ4°X±LÐAÓBÐBØ×Ñ˜ÔÜˆx‹=Ðr   c                ó<   € V ^8„  d   QhR\         R\        R\        /# rÔ  rô  )r   s   "r   r   r   Ì  s&   € ÷ Nñ N´ð NÄð NÌñ Nr   c              ƒ  óT   "  € \         P                  ! \        W4      G Rj  x€L
 #  L5i)z>Cache document bytes without blocking the caller's event loop.N)r   r   rÝ  )rÓ  rÕ  s   &&r   Úcache_document_from_bytes_asyncrà  Ì  s   é € ä×"Ò"Ô#<¸dÓM×MÐMÑMùr  c                   óB   a € ] tR tRt o RtV 3R lR ltV 3R ltRtV tR# )ÚCachedMediaiÒ  z)Result of caching one attachment's bytes.c                ó    <€ V ^8„  d   QhRS[ /# rj   rk   )r   Ú__classdict__s   "€r   r   ÚCachedMedia.__annotate__Ú  s   ø€ ÷ iñ i™cñ ir   c                ón   € ^ RI Hp RV P                   RV P                   RV! V P                  4       R2# )zûOne-line transcript annotation pointing the agent at the file (sandbox-translated at
render time, never baked into ``path``: ``event.media_urls`` must hold one coordinate
system so the routed turn can re-home and translate every entry alike, #101134).)Úto_agent_visible_cache_pathÚ[z 'z' saved at: Ú])r%  rç  r«   Údisplay_namer6   )Úselfrç  s   & r   Úcontext_noteÚCachedMedia.context_noteÚ  s=   € õ 	GØ�4—9‘9�+˜R × 1Ñ 1Ð2°,Ñ?ZÐ[_×[dÑ[dÓ?eÐ>fÐfgÐhÐhr   c                óJ   <€ V ^8„  d   Qh/ S[ ;R&   S[ ;R&   S[ ;R&   S[ ;R&   # )r   r6   r   r«   rê  rk   )r   rä  s   "€r   r   rå  Ò  s6   ø‡ ‚ ñ �Iñ ñ �Oñ	 ñ
 �Iñ ñ Ñò r   rt   N)	rÎ  Ú
__module__rÏ  Ú__firstlineno__Ú__doc__rì  Ú__annotate_func__Ú__static_attributes__Ú__classdictcell__©rä  s   @r   râ  râ  Ò  s   ø‡ € á3÷ið i÷ ƒ r   râ  c                ó<   € V ^8„  d   QhR\         R\         R\         /# )r   rÕ  Ú	mime_typer   rk   )r   s   "r   r   r   ê  s&   € ÷ Bñ B¤ð B´ð B¼ñ Br   c                óî   € V '       d5   \         P                  P                  V 4      ^,          P                  4       MRpT;'       g/    \        P                  T;'       g    RP                  4       R4      # )z=Best-effort file extension from filename, then MIME fallback.rn   )rP   r6   Úsplitextrp   Ú_MIME_TO_EXTr¥   )rÕ  r÷  r²   s   && r   Ú_resolve_media_extrû  ê  sR   € ç3;Œ"�'‰'×
Ñ
˜8Ó
$ QÕ
'×
-Ñ
-Ô
/À€CØ×AÐA”,×"Ñ" I§O O°×#:Ñ#:Ó#<¸bÓAÐAr   rÕ  r÷  Údefault_kindc                ó€   € V ^8„  d   QhR\         R\        R\        R\        \        ,          R\        \        ,          /# ©r   rÓ  rÕ  r÷  rü  r   ©r¨  r8   rf  râ  )r   s   "r   r   r   ð  sA   € ÷ Mñ MœEð M´ð MÄSð MÜ$,¬S¥MðMÜ=EÄkÕ=RñMr   c               ó  € \        W4      pT;'       g    RP                  4       pV'       d   \        P                  ! RRV4      MVP	                  R4      ;'       g    RpR\
        R\        R3R	\        R
\        R3R\        R\        R33 F{  w  rxršpVP                  V R24      '       g   WH9   g	   W78X  g   K/  WH9   d   TMT	p V
! WR7      pT'       d   TP                  T R24      '       d   TMYŒ,          p\        YÞYv4      u # 	  T;'       g    V'       d   RV 2MRp\        W4      p\        P!                  V4      ;'       g    T;'       g    Rp\        YÞRT;'       g    T4      #   \         d    TR8w  d   h   R# i ; i)zÜClassify and cache raw attachment bytes -> CachedMedia (None only for images failing
validation). ``default_kind`` biases ambiguous ext/MIME (Telegram native photo, no name);
anything not image/video/audio is a document.rn   z	[^\w.\- ]rí   rÃ   Úfiler©   r,   Tr¨   r'   Fr§   r    ré  )r²   NrL  zdocument.binzapplication/octet-stream)rû  rp   r�  r¼  r}  ÚSUPPORTED_IMAGE_DOCUMENT_TYPESrü  ÚSUPPORTED_VIDEO_TYPESrF  Ú_AUDIO_MIME_TYPESr9  r=  rñ   râ  rÝ  ÚSUPPORTED_DOCUMENT_TYPESr¥   )rÓ  rÕ  r÷  rü  r²   ÚmimeÚdisplayr«   ÚtableÚdefault_extr  ÚpassthroughÚkind_extr6   Úout_mimeÚfallback_names   &$$$            r   Úcache_media_bytesr  ð  sv  € ô
 ˜XÓ
1€CØ�OˆO˜×"Ñ"Ó$€Dß5=Œb�fŠf�\ 3¨Ô1ÀCÇJÁJÈsÃO×D]ÐD]ÐW]€Gð Ô4°fÔ>TÐVZÐ[ØÔ+¨VÔ5KÈUÐSØÔ'¨Ô1GÈÐNó<PÑ7ˆ�[¨Kð —‘ 4 &¨ 
×+Ò+¨s¬|¸|Ô?SÙØœ,‘3¨Kˆð	Ù˜DÔ/ˆD÷
 '¨4¯?©?¸d¸VÀ1¸:×+FÒ+F‘4ÈEÍOˆÜ˜4¨4Ó9Ò9ñ<Pð" ×MÐM·S 8¨C¨5Ñ!1¸n€MÜ$ TÓ9€DÜ'×+Ñ+¨CÓ0×VÐV°D×VÐVÐ<V€HÜ�t z°7×3KÐ3K¸mÓLÐLøô ô 	Ø�wŒØÛð	ús   Ã	E0Å0FÆFc                ó€   € V ^8„  d   QhR\         R\        R\        R\        \        ,          R\        \        ,          /# rþ  rÿ  )r   s   "r   r   r     sE   € ÷ ñ Ü
ðô ðô ð	ô
 œ3•-ðô ŒkÕñr   c             ƒ  ó\   "  € \         P                  ! \        V VVVR7      G Rj  x€L
 #  L5i)zDClassify and cache attachment bytes without blocking the event loop.)rÕ  r÷  rü  N)r   r   r  )rÓ  rÕ  r÷  rü  s   &$$$r   Úcache_media_bytes_asyncr    s3   é € ô ×"Ò"ÜØØØØ!ô÷ ð ñ ùs   ‚#,¥*¦,c                   óF   a € ] tR tRt o RR/V 3R lR lltV 3R ltRtV tR# )ÚTextDebounceStatei!  ÚunlessNc                óF   <€ V ^8„  d   QhRS[ P                  R,          RR/# )r   r  Nr   r   )r   rä  s   "€r   r   ÚTextDebounceState.__annotate__(  s$   ø€ ÷ ñ ¡g§l¡l°TÕ&9ð ÀTñ r   c               óÂ   € V P                   eQ   V P                   VJd?   V P                   P                  4       '       g   V P                   P                  4        R# R# R# R# )z<Cancel the pending flush timer (if live and not ``unless``).N)r   ÚdoneÚcancel)rë  r  s   &$r   Úcancel_timerÚTextDebounceState.cancel_timer(  sD   € à�9‰9Ò  T§Y¡Y°fÓ%<ÀTÇYÁYÇ^Á^×EUÒEUØ�I‰I×ÑÖñ FVÑ%<Ñ r   c                ól   <€ V ^8„  d   Qh/ S[ ;R&   S[P                  R,          ;R&   S[;R&   S[;R&   # )r   r–   Nr   Úfirst_tsÚlast_ts)rz  r   r   r¨  )r   rä  s   "€r   r   r  !  s>   ø‡ ‚ áÑñ ñ �,‰,˜Õ
Ññ ñ �Oñ	 ñ
 �Nò r   rt   )rÎ  rï  rÏ  rð  r  rò  ró  rô  rõ  s   @r   r  r  !  s   ø‡ € ð¸D÷ ò ÷ ƒ r   r  c                óh   € V ^8„  d   QhR\         \        ,          R\         \        ,          R\        /# )r   ÚexistingÚnewr   ©rf  r8   )r   s   "r   r   r   .  s)   € ÷ 5ñ 5œ8¤C�=ð 5¬x¼­}ð 5Äñ 5r   c                ó$   € V '       d   V  RV 2# T# )zC``existing\nnew`` when both non-empty; the non-empty one otherwise.r†  rt   )r   r!  s   &&r   Ú_append_textr$  .  s   € ç#+ˆhˆZ�r˜#˜ÐÐ4°Ð4r   c                   ó0   a € ] tR tRt o RtV 3R ltRtV tR# )Ú_ExtractedResponsei3  zLDeliverable parts of a handler response (see ``_extract_response_content``).c                ób   <€ V ^8„  d   Qh/ S[ ;R&   S[;R&   S[;R&   S[;R&   S[;R&   S[ ;R&   # )r   Útext_contentrT  Úmedia_filesÚlocal_filesÚforce_document_attachmentsÚpre_extract)r8   r$  rµ   )r   rä  s   "€r   r   Ú_ExtractedResponse.__annotate__3  sR   ø‡ ‚ ñ Ññ ñ �Lñ	 ñ
 Ññ ñ Ññ ñ !%Ñ$ñ ñ Ñò r   rt   N)rÎ  rï  rÏ  rð  rñ  rò  ró  rô  rõ  s   @r   r&  r&  3  s   ø‡ € áV÷ ƒ r   r&  z4^(?:please\s+)?restart\s+(?:the\s+)?gateway[.!?\s]*$z=^(?:please\s+)?restart\s+(?:the\s+)?hermes\s+gateway[.!?\s]*$z(^(?:please\s+)?restart\s+hermes[.!?\s]*$c                ó(   € V ^8„  d   QhR\         RR/# ©r   r–   r   N©rz  )r   s   "r   r   r   D  s   € ÷ $ñ $¬Lð $¸Tñ $r   c           	     ól  a€ \         P                  ! \        4      ;_uu_ 4        V e    V P                  \        P
                  8w  d    RRR4       R# V P                  ;'       g    RP                  4       oS'       d   SP                  R4      '       d    RRR4       R# \        \        V RR4      RR4      R8w  d    RRR4       R# \        ;QJ d#    V3R l\         4       F  '       g   K   RM	  R	M! V3R l\         4       4      '       d   R
V n        RRR4       R#   + '       g   i     R# ; i)zÿRewrite a tiny set of DM plaintext admin phrases (exact matches only) into slash commands so
``restart gateway`` never reaches the LLM/tool path (a self-restart from inside the running
agent leaves the gateway stuck in ``draining`` waiting on that agent).Nrn   ré  rŒ   rƒ   r„   c              3   óD   <"  € T F  qP                  S4      x € K  	  R # 5ir¼  )rí  )rì   Úpatternr   s   & €r   rï   Ú3coerce_plaintext_gateway_command.<locals>.<genexpr>P  s   øé € ÐVÑ2U w�}‰}˜T×"Ð"Ó2Uùs   ƒ TFz/restart)r\   r]   r[   Úmessage_typer{  ÚTEXTr   r‹   r=  ro   rö   Ú#_PLAINTEXT_GATEWAY_RESTART_PATTERNS)r–   r   s   &@r   Ú coerce_plaintext_gateway_commandr8  D  sÓ   ø€ ô 
×	Ò	œY×	'Õ	'ØŠ=˜E×.Ñ.´+×2BÑ2BÔBØ÷ 
(Ñ	'ð —
‘
× Ð ˜b×'Ñ'Ó)ˆß�t—‘ s×+Ò+Ø÷ 
(Ñ	'ô ”7˜5 (¨DÓ1°;ÀÓEÈÔMØ÷ 
(Ñ	'÷ ‹3ÔVÕ2UÓV�3�3Š3ÔVÕ2UÓV×VÒVØ#ˆEŒJ÷ 
(×	'×	'Ò	'úsA   ¤%D"ÁD"Á&D"Á?D"ÂD"Â!D"Ã	
D"ÃD"Ã/!D"ÄD"Ä"D3	c                   óP   a € ] tR tRt o RtRt]V 3R lR l4       tV 3R ltRt	V t
R# )ÚExecApprovalPromptiT  ud  One exec-approval prompt, ready for a platform to render natively (see
``BasePlatformAdapter.send_exec_approval``). ``actions`` rows are ``(label, choice, style)``
with ``choice`` in ``once`` / ``session`` / ``always`` / ``deny`` â€” the vocabulary
``tools.approval.resolve_gateway_approval`` accepts â€” and ``style`` in ``primary`` /
``danger`` / ``""``.Nc                ó0   <€ V ^8„  d   QhRS[ S[,          /# rj   )r$  r8   )r   rä  s   "€r   r   ÚExecApprovalPrompt.__annotate__e  s   ø€ ÷ 9ñ 9™™c�ñ 9r   c                óN   € V P                    UUu. uF  w  rqNK	  	  upp# u uppi r¼  )Úactions)rë  rí   Úchoices   &  r   ÚchoicesÚExecApprovalPrompt.choicesd  s"   € à+/¯<ª<Ô8©<™<˜1 a’©<Ò8Ð8ùÓ8s   �!c                óÊ   <€ V ^8„  d   Qh/ S[ ;R&   S[ ;R&   S[ ;R&   S[S[S[ S[ S[ 3,          ,          ;R&   S[ ;R&   S[ ;R&   S[;R&   S[S[S[ S[3,          ,          ;R&   # )	r   Úchat_idrú  r   r>  ÚcommandÚdescriptionÚsmart_deniedr�   )r8   r$  r%  rµ   rf  r|   rg  )r   rä  s   "€r   r   r<  T  s‡   ø‡ ‚ ñ �Lñ ñ Ññ ñ �Iñ ñ ‘%™™S¡#˜Õ&Õ'Ñ'ñ ñ �Lñ ñ Ññ ñ Ññ ñ ‘t™C¡˜H•~Õ&Ñ-ò r   rt   )rÎ  rï  rÏ  rð  rñ  r�   Úpropertyr@  rò  ró  rô  rõ  s   @r   r:  r:  T  s*   ø‡ € ñð *.€Hà÷9ó ð9÷# ƒ r   r:  c                   óL   a € ] tR tRt o RtRtRtRtRtRt	Rt
RtV 3R ltRtV tR# )Ú
SendResultii  zResult of sending a message.NFc                óº   <€ V ^8„  d   Qh/ S[ ;R&   S[S[,          ;R&   S[S[,          ;R&   S[;R&   S[ ;R&   S[S[,          ;R&   S[;R&   S[S[,          ;R&   # )	r   Úsuccessr‡   r   Úraw_responseÚ	retryableÚretry_afterÚcontinuation_message_idsÚ
error_kind)rµ   rf  r8   rg  r¨  r%  )r   rä  s   "€r   r   ÚSendResult.__annotate__i  s|   ø‡ ‚ ñ �Mñ ñ ™•Ñ$ñ	 ñ
 ‘C�=Ññ ñ Ññ ñ Ññ ñ ™%•Ñ'ñ ñ $Ñ(ñ ñ  ™•Ñ$ò! r   rt   )rÎ  rï  rÏ  rð  rñ  r‡   r   rL  rM  rN  rO  rP  rò  ró  rô  rõ  s   @r   rI  rI  i  s9   ø‡ € á&à $€JØ€Eð €LØ€IØ#'€Kð ')Ðð !%€J÷! ƒ r   rI  Útoo_longÚ
bad_formatÚ	forbiddenÚ	not_foundÚrate_limitedÚ	transientc                óR   € V ^8„  d   QhR\         \        ,          R\        R\        /# ©r   r   Ú
error_textr   ©rf  ÚBaseExceptionr8   )r   s   "r   r   r   �  s&   € ÷ #ñ #”XœmÕ,ð #Äð #Ìcñ #r   c                óÐ   € V'       d   V.M. pV e8   VP                  R \        V 4      V P                  P                  3 4       4       RP	                  V4      P                  4       # )u–   Lowercased blob (error_text + str(exc) + exception class name) that both
send-error classifiers match against â€” one builder so they can never drift.c              3   ó8   "  € T F  q'       g   K  Vx € K  	  R # 5ir¼  rt   rq  s   & r   rï   Ú_error_blob.<locals>.<genexpr>•  s   é € ÐHÑ B˜1Ãa—Q’QÓ Bùs   ‚	�
rÈ  )r“  r8   Ú	__class__rÎ  rÆ   rp   )r   rZ  Úpartss   && r   Ú_error_blobrb  �  sP   € ÷ 'ˆZ‰L¨B€EØ
‚Ø�‰ÑH¤ S£¨3¯=©=×+AÑ+AÑ BÓHÔHØ�8‰8�E‹?× Ñ Ó"Ð"r   c                ó<   € V ^8„  d   QhR\         R\         R\        /# )r   ÚblobÚneedlesr   r´   )r   s   "r   r   r   ™  s!   € ÷ +ñ +”#ð +¤ð +¬ñ +r   c                 óx   a € \         ;QJ d    V 3R  lV 4       F  '       g   K   R# 	  R# ! V 3R  lV 4       4      # )c              3   ó,   <"  € T F	  qS9   x € K  	  R # 5ir¼  rt   )rì   Únrd  s   & €r   rï   Ú_any_in.<locals>.<genexpr>š  s   øé € Ð*¡'˜Q�DŽy£'ùó   ƒTF)rö   )rd  re  s   f*r   Ú_any_inrk  ™  s,   ø€ ß‹3Ô*¡'Ó*�3Œ3Ð*Š3Ð*ˆ3Ô*¡'Ó*Ó*Ð*r   c                 ó   € \        V R RR4      # )Úmessage_too_longztoo longzmessage is too long©rk  ©Úbs   &r   rš  rš  Ÿ  s   € œ7 1Ð&8¸*ÐF[Ô\r   c                 óˆ   € \        V R RRR4      ;'       g-    RV 9   ;'       d    RV 9   ;'       g    RV 9   ;'       d    RV 9   # )zcan't parse entitieszcant parse entitieszcan't find endzunsupported start tagÚentityÚparsezbad requestÚentitrn  ro  s   &r   rš  rš     sV   € Ü�Ð)Ð+@ÐBRÐTkÓl÷ 	1ð 	1Ø˜‰M×*Ð*˜g¨™l÷	1ð 	1à˜QÑ×/Ð/ 7¨a¡<ð	1r   c           
      ó&   € \        V R RRRRRR4      # )rT  zbot was blockedzblocked by the userzuser is deactivatedznot enough rightszhave no rightsznot a memberrn  ro  s   &r   rš  rš  ¤  s   € œGØ	ˆ;Ð)Ð+@ÐBWØÐ-¨~ô?r   c                 ó0   € \        V .\        O\        O5!  # r¼  )rk  Ú _CHAT_LEVEL_NOT_FOUND_SUBSTRINGSÚ_SUBCHAT_NOT_FOUND_SUBSTRINGSro  s   &r   rš  rš  §  s   € œG AÐiÔ(HÐiÔKhÔir   c                 ó    € \        V R RRR4      # )Úfloodztoo many requestszretry afterz
rate limitrn  ro  s   &r   rš  rš  ¨  s   € œw q¨'Ð3FÈÐWcÔdr   c                 ó(   € \        V .\        OR N5!  # )Úconnecttimeout)rk  Ú_RETRYABLE_ERROR_PATTERNSro  s   &r   rš  rš  ©  s   € œG AÐTÔ(AÐTÐCSÔTr   c                óR   € V ^8„  d   QhR\         \        ,          R\        R\        /# rY  r[  )r   s   "r   r   r   ¬  s+   € ÷ añ aœX¤mÕ4ð aÄ#ð aÌsñ ar   c                óN   a€ \        W4      o\        V3R l\         4       R4      # )z®Map a send exception / error string to a :data:`SEND_ERROR_KINDS` value; anything
unrecognized is ``"unknown"`` so an unclassified failure is never mistaken for a benign one.c              3   óL   <"  € T F  w  rV! S4      '       g   K  Vx € K  	  R # 5ir¼  rt   )rì   r«   Úmatchesrd  s   &  €r   rï   Ú&classify_send_error.<locals>.<genexpr>°  s   øé € ÐTÑ+B™-˜$ÁgÈdÇm—’Ó+Bùs   ƒ$š
$Úunknown)rb  ÚnextÚ_SEND_ERROR_CLASSIFIERS©r   rZ  rd  s   &&@r   Úclassify_send_errorr‡  ¬  s$   ø€ ô �sÓ'€DÜÔTÕ+BÓTÐV_Ó`Ð`r   c                óR   € V ^8„  d   QhR\         \        ,          R\        R\        /# rY  )rf  r\  r8   rµ   )r   s   "r   r   r   ³  s,   € ÷ Bñ B¤¬-Õ!8ð BÌSð BÔZ^ñ Br   c                óv   € \        W4      p\        V.\        O5!  '       * ;'       d    \        V.\        O5!  # )zàWhether a ``not_found`` failure means the *whole chat* is gone (only that marks a target
dead; a deleted topic / edited-away message leaves the parent chat reachable). When both
markers are present the sub-chat reading wins.)rb  rk  rx  rw  r†  s   && r   Úis_chat_level_not_foundrŠ  ³  s?   € ô �sÓ'€DÜ˜Ð=Ô<Ó=Ô=÷ Að AÜ˜Ð@Ô?Ó@ðBr   c                   ón   a a€ ] tR tRt oRtR	V3R lV 3R lllt]V3R lR l4       tV3R ltRt	Vt
V ;t# )
ÚEphemeralReplyi¼  aZ  System-notice reply that auto-deletes after ``ttl_seconds`` on platforms implementing
``delete_message`` (others leave it). ``None`` ttl uses ``display.ephemeral_system_ttl``
(``0`` disables globally). Subclassing ``str`` keeps it transparent to everything that
treats handler results as text; ``isinstance`` lets the send path schedule deletion.c                ó6   <€ V ^8„  d   QhRS[ RS[S[,          /# )r   r   Úttl_seconds)r8   rf  r9   )r   rä  s   "€r   r   ÚEphemeralReply.__annotate__Ã  s   ø€ ÷ ñ ™3ð ©X±c­]ñ r   c                ó2   <€ \         SV `  W4      pW#n        V# r¼  )ÚsuperÚ__new__rŽ  )Úclsr   rŽ  Úinstancer`  s   &&& €r   r’  ÚEphemeralReply.__new__Ã  s   ø€ Ü‘7‘? 3Ó-ˆØ*ÔØˆr   c                ó    <€ V ^8„  d   QhRS[ /# rj   rk   )r   rä  s   "€r   r   r�  É  s   ø€ ÷ !ñ !‘cñ !r   c                ó,   € \         P                  V 4      # )z6The underlying text (explicit form of ``str(reply)``).)r8   Ú__str__©rë  s   &r   r   ÚEphemeralReply.textÈ  s   € ô �{‰{˜4Ó Ð r   c                ó6   <€ V ^8„  d   Qh/ S[ S[,          ;R&   # )r   rŽ  ©rf  r9   )r   rä  s   "€r   r   r�  ¼  s   ø‡ ‚ ñ
 ™#•Ñò r   rt   r¼  )rÎ  rï  rÏ  rð  rñ  r’  rG  r   rò  ró  rô  Ú__classcell__)r`  rä  s   @@r   rŒ  rŒ  ¼  s0   ù‡ € ñ\÷õ ð
 ÷!ó ð!÷ … r   rŒ  Ú
merge_textc          
      ón   € V ^8„  d   QhR\         \        \        3,          R\        R\        R\        RR/# )r   Úpending_messagesrú  r–   rž  r   N)r|   r8   rz  rµ   )r   s   "r   r   r   Î  s=   € ÷ .*ñ .*´$´s¼LÐ7HÕ2Ið .*ÔX[ð .*Ü'3ð.*ÜDHð.*ØUYñ.*r   c               óh  € V P                  V4      pV'       Ed”   \        VRR4      pV\        P                  8H  pVP                  \        P                  8H  pT;'       d    Tp\        VP                  4      p	R R lp
. pV	'       d   V
! V4      Vn        V
! V4      pV'       g   VP                  '       g
   V	'       Ed\   V'       g	   V	'       df   VP                  P                  VP                  4       VP                  P                  VP                  4       VP                  P                  V4       VP                  '       d0   \        P                  VP                  VP                  4      Vn
        VP                  V4       V'       g	   V'       d   \        P                  Vn        MEV\        P                  8X  d1   VP                  \        P                  8w  d   VP                  Vn        R F!  p\        WL4      '       g   K  \!        WL4       K#  	  R# V\        P                  8H  ;'       d    VP                  \        P                  8H  pV'       dS   V'       dK   VP                  '       d&   \#        VP                  VP                  4      Vn
        VP                  V4       R# W V&   R# )z»Store or merge a pending event: photo bursts/albums merge into the queued event so the next
turn sees the whole burst; with ``merge_text`` rapid TEXT follow-ups append instead of
replace.r5  Nc                ó\   € V ^8„  d   QhR\         R\        \        \        ,          ,          /# )r   Úmsgr   )rz  r$  rf  rµ   )r   s   "r   r   Ú1merge_pending_message_event.<locals>.__annotate__Û  s'   € ÷ 	Gñ 	G¤lð 	G´t¼HÄT½NÕ7Kñ 	Gr   c                 óª   € \        \        V R . 4      ;'       g    . 4      pVR.\        V P                  4      \        V4      ,
          ,          ,           # )Úmedia_text_inlinedN)r$  ro   rÒ   Ú
media_urls)r£  Úflagss   & r   Ú_padded_inline_flagsÚ9merge_pending_message_event.<locals>._padded_inline_flagsÛ  sB   € Üœ Ð&:¸BÓ?×EÐEÀ2ÓFˆEØ˜D˜6¤S¨¯©Ó%8¼3¸u»:Õ%EÕFÕFÐFr   )Ú_gateway_pending_stt_textÚ _gateway_pending_stt_transcripts)r¥   ro   r{  ÚPHOTOr5  rµ   r§  r¦  r“  Úmedia_typesr   r¦  Ú_merge_captionÚabsorb_reply_expectedr6  ÚhasattrÚdelattrr$  )r   rú  r–   rž  r   Úexisting_typeÚexisting_is_photoÚincoming_is_photoÚ
both_photoÚincoming_has_mediar©  Úincoming_inline_flagsÚattrÚ	both_texts   &&&$          r   Úmerge_pending_message_eventr»  Î  s  € ð
  ×#Ñ# KÓ0€Hß€xÜ ¨.¸$Ó?ˆØ)¬[×->Ñ->Ñ>ÐØ!×.Ñ.´+×2CÑ2CÑCÐØ&×<Ð<Ð+<ˆ
Ü! %×"2Ñ"2Ó3Ðõ	Gð 79ÐßÙ*>¸xÓ*HˆHÔ'Ù$8¸Ó$?Ð!÷ ˜×,×,Ð,×0BÐ0Bß×/Ø×#Ñ#×*Ñ*¨5×+;Ñ+;Ô<Ø×$Ñ$×+Ñ+¨E×,=Ñ,=Ô>Ø×+Ñ+×2Ñ2Ð3HÔIØ�z�zˆzÜ 3× BÑ BÀ8Ç=Á=ÐRW×R\ÑR\Ó ]�”Ø×*Ñ*¨5Ô1ß ×$5Ü(3×(9Ñ(9�Õ%Ø¤+×"2Ñ"2Ô2°u×7IÑ7IÌ[×M]ÑM]Ô7]Ø(-×(:Ñ(:�Ô%ó Z�Ü˜8×*Ô*Ü˜HÖ+ñ Zñ Ø!¤[×%5Ñ%5Ñ5×`Ð`¸%×:LÑ:LÔP[×P`ÑP`Ñ:`ˆ	ßŸ)Ø�z�zˆzÜ ,¨X¯]©]¸E¿J¹JÓ G�”Ø×*Ñ*¨5Ô1ÙØ$)�[Ó!r   c          	      ód   € V ^8„  d   QhR\         R\        R\        R,          R\        R,          /# ©r   Úconfig_extraÚ
channel_idÚ	parent_idNr   ©r|   r8   )r   s   "r   r   r   	  s4   € ÷ 
ñ 
¬ð 
¼3ð 
Ì3ÐQUÍ:ð 
ÔadÐgkÕakñ 
r   c                ó  € V P                  R4      ;'       g    / p\        V\        4      '       g   R# W3 FI  pV'       d   VP                  V4      MRpVf   K$  \        V4      P	                  4       ;p'       g   KG  Vu # 	  R# )zµPer-channel ephemeral prompt from ``config.extra["channel_prompts"]``: exact *channel_id*
first, then *parent_id* (threads inherit the parent prompt). Blank prompts count as absent.Úchannel_promptsN)r¥   r¤   r|   r8   r‹   )r¾  r¿  rÀ  Úpromptsr  Úprompts   &&&   r   Úresolve_channel_promptrÆ  	  sv   € ð ×ÑÐ0Ó1×7Ð7°R€GÜ�gœt×$Ò$ÙØÓ&ˆß%(�—‘˜SÔ!¨dˆØÔ¬S°«[×->Ñ->Ó-@Ð#@ 6×#@Ð#@ØŠMñ 'ñ r   c          	      óz   € V ^8„  d   QhR\         R\        R\        R,          R\        \        ,          R,          /# r½  )r|   r8   r$  )r   s   "r   r   r     s:   € ÷ ñ ÜðÜ$'ðÜ47¸$µJðÜJNÌsÍ)ÐVZÕJZñr   c                ó²  a€ V P                  R4      ;'       g    . p\        V\        4      '       d	   V'       g   R# R W3 4        EF  pV EF   p\        V\        4      '       d!   \	        VP                  RR4      4      V8w  d   K<  VP                  R4      ;'       g    VP                  R4      p\        V\        4      '       d.   VP                  4       '       d   VP                  4       .MRu u # \        V\        4      '       g   KÁ  V'       g   KË  \        P                  V3R lV 4       4      p\        V4      ;'       g    Ru u # 	  EK  	  R# )	a  Auto-loaded skill(s) for a channel/thread from ``channel_skill_bindings`` (entries
``{id: "<channel/forum id>", skills: [...]}``; ``skill: "<name>"`` also accepted). Exact
*channel_id* first, then *parent_id* (threads inherit). Deduplicated ordered list or None.Úchannel_skill_bindingsNc              3   óJ   "  € T F  q'       g   K  \        V4      x € K  	  R # 5ir¼  rk   )rì   r  s   & r   rï   Ú)resolve_channel_skills.<locals>.<genexpr>  s   é € ÐFÑ'> Ã#”8”3�s—8�8Ó'>ùs   ‚	#�#Úidrn   ÚskillsÚskillc              3   óŒ   <"  € T F9  p\        V\        4      '       g   K  VP                  4       ;o'       g   K5  Sx € K;  	  R # 5ir¼  )r¤   r8   r‹   )rì   rF  Únms   & €r   rï   rË  '  s2   øé € ð %]Ù#)˜4¬Z¸¼c×-B”BÈdÏjÉjËlÐHZÈÓHZ—B’B£6ùs   ƒA Aº
A)r¥   r¤   r$  r|   r8   r‹   r}  )	r¾  r¿  rÀ  ÚbindingsÚwantedrò  rÍ  ÚseenrÐ  s	   &&&     @r   Úresolve_channel_skillsrÔ    s  ø€ ð
 ×ÑÐ 8Ó9×?Ð?¸R€HÜ�h¤×%Ò%¯XÙáF¨
Ñ'>×FˆÜˆEÜ˜e¤T×*Ò*¬c°%·)±)¸DÀ"Ó2EÓ.FÈ&Ô.PÙØ—Y‘Y˜xÓ(×>Ð>¨E¯I©I°gÓ,>ˆFÜ˜&¤#×&Ò&Ø+1¯<©<¯>ª>˜Ÿ™›Ñ'¸tÔCÜ˜&¤$×'Ô'¯F©FÜ—}‘}ô %]Ù#)ó%]ó ]�ä˜D“z×)Ð) TÔ)ô ñ Gñ r   c                óh   € V ^8„  d   QhR\         R\        \        \        ,          \         3,          /# )r   rò  r   )rg  r%  rf  r9   )r   s   "r   r   r   -  s,   € ÷ Tñ T¤cð T¬e´H¼SµMÄ3Ð4FÕ.Gñ Tr   c                óZ   € \        V \        4      '       d   \        V 4      ^8X  d   V # RV 3# )z_``(generation, callback)`` from a post-delivery slot; legacy bare callbacks have no
generation.N)r¤   r%  rÒ   )rò  s   &r   Ú_split_post_delivery_entryr×  -  s)   € ô ˜u¤e×,Ò,´°U³¸q´ˆ5ÐSÀtÈUÀmÐSr   c                ób   € V ^8„  d   QhR\         R\        R\        . \         3,          R\         /# )r   ÚobjrF  Úfactoryr   )rg  r8   rh  )r   s   "r   r   r   3  s1   € ÷ ñ ”Cð œsð ¬X°b¼#°gÕ->ð Ä3ñ r   c                óL   € \        WR4      pVf   V! 4       p\        WV4       V# )uš   ``getattr(obj, name)`` or create it via ``factory`` â€” the getattr-guard for
tests that build adapters via ``object.__new__`` and never run ``__init__``.N)ro   Úsetattr)rÙ  rF  rÚ  rm   s   &&& r   Ú
_lazy_attrrÝ  3  s+   € ô �C˜tÓ$€EØ‚}Ù“	ˆÜ�˜5Ô!Ø€Lr   c                   ó�  a € ] tR tRt o RtRtRtV 3R lR ltRtRt	Rt
RtRtRtRtV 3R	 lR
 lt]V 3R lR l4       tV 3R lR ltV 3R lR lt]V 3R lR l4       t]V 3R lR l4       tERÁV 3R lR lltERÂV 3R lR lltV 3R lR ltERÂV 3R lR lltV 3R lR ltRR R!^(/V 3R" lR# lltV 3R$ lR% lt]! R& 4      t]! R' 4      t]! R( 4      t]! R) 4      t V 3R* lR+ lt!V 3R, lR- lt"R.t#]V 3R/ lR0 l4       t$R1R/V 3R2 lR3 llt%V 3R4 lR5 lt&V 3R6 lR7 lt'V 3R8 lR9 lt(V 3R: lR; lt)V 3R< lR= lt*V 3R> lR? lt+V 3R@ lRA lt,Rt-Rt.ERÂV 3RB lRC llt/V 3RD lRE lt0]V 3RF lRG l4       t1]V 3RH lRI l4       t2V 3RJ lRK lt3V 3RL lRM lt4V 3RN lRO lt5V 3RP lRQ lt6V 3RR lRS lt7V 3RT lRU lt8V 3RV lRW lt9ERÃRXRRYR/V 3RZ lR[ lllt:V 3R\ lR] lt;V 3R^ lR_ lt<V 3R` lRa lt=V 3Rb lRc lt>V 3Rd lRe lt?ERÂV 3Rf lRg llt@RhtARitBRitCRjtDRktERltFRmtGRnRiRoR/V 3Rp lRq lltHV 3Rr lRs ltIV 3Rt lRu ltJV 3Rv lRw ltKV 3Rx lRy ltLV 3Rz lR{ ltMV 3R| lR} ltNV 3R~ lR ltOV 3R€ lR� ltPV 3R‚ lRƒ ltQV 3R„ lR… ltRV 3R† lR‡ ltSV 3Rˆ lR‰ ltT]URŠR/V 3R‹ lRŒ ll4       tV]UV 3R� lRŽ l4       tW]UERÃV 3R� lR� ll4       tXRtYV 3R‘ lR’ ltZR“R/V 3R” lR• llt[V 3R– lR— lt\V 3R˜ lR™ lt]V 3Rš lR› lt^Rœt_R�t`RžtaRŸtb^ tc]V 3R  lR¡ l4       td]V 3R¢ lR£ l4       te]V 3R¤ lR¥ l4       tf]gERÄV 3R¦ lR§ ll4       thV 3R¨ lR© ltiERÅV 3Rª lR« lltjV 3R¬ lR­ ltkV 3R® lR¯ ltlERÆV 3R° lR± lltmR²R³R´Rµ/tn]V 3R¶ lR· l4       toV 3R¸ lR¹ ltp]qV 3Rº lR» l4       trERÇV 3R¼ lR½ lltsV 3R¾ lR¿ ltt]gV 3RÀ lRÁ l4       tuERÂV 3RÂ lRÃ lltvERÂV 3RÄ lRÅ lltwERÃV 3RÆ lRÇ lltxERÂV 3RÈ lRÉ lltyV 3RÊ lRË ltz]gV 3RÌ lRÍ l4       t{ERÂV 3RÎ lRÏ llt|ERÈV 3RÐ lRÑ llt}ERÁV 3RÒ lRÓ llt~ERÁV 3RÔ lRÕ llt]gV 3RÖ lR× l4       t€]gV 3RØ lRÙ l4       t�ERÁV 3RÚ lRÛ llt‚RÜR/V 3RÝ lRÞ lltƒRßRRàRRáR/V 3Râ lRã llt„RäRRßRRàRRåR/V 3Ræ lRç llt…ERÉRáRRèRRàR/V 3Ré lRê lllt†ERÂRèRRàR/V 3Rë lRì lllt‡V 3Rí lRî ltˆV 3Rï lRð lt‰V 3Rñ lRò ltŠERÂV 3Ró lRô llt‹V 3Rõ lRö ltŒR÷R/V 3Rø lRù llt�ERÂV 3Rú lRû lltŽERÂRüR/V 3Rý lRþ lllt�ERÂRüR/V 3Rÿ lER  lllt�ERÂRüR/V 3ER lER lllt‘ERÁV 3ER lER llt’ERÊV 3ER lER llt“ERRRàR/V 3ER lER	 llt”ERÁV 3ER
 lER llt•]gERÉV 3ER lER ll4       t–]gERËV 3ER lER ll4       t—]gERÉV 3ER lER ll4       t˜]gV 3ER lER l4       t™]gV 3ER lER l4       tš]gV 3ER lER l4       t›]gV 3ER lER l4       tœ]gV 3ER lER l4       t�ERÌV 3ER lER lltžERÂRàRERERER ^/V 3ER! lER" llltŸERÂV 3ER# lER$ llt V 3ER% lER& lt¡V 3ER' lER( lt¢ERÂV 3ER) lER* llt£ER+R/V 3ER, lER- llt¤]gV 3ER. lER/ l4       t¥ER+R/V 3ER0 lER1 llt¦Rt§Rt¨Rt©V 3ER2 lER3 ltªV 3ER4 lER5 lt«V 3ER6 lER7 lt¬]gV 3ER8 lER9 l4       t­]gV 3ER: lER; l4       t®]gV 3ER< lER= l4       t¯V 3ER> lER? lt°ER@R/V 3ERA lERB llt±V 3ERC lERD lt²V 3ERE lERF lt³]´ERÍV 3ERG lERH ll4       tµV 3ERI lERJ lt¶]gV 3ERK lERL l4       t·V 3ERM lERN lt¸V 3ERO lERP lt¹]gV 3ERQ lERR l4       tºV 3ERS lERT lt»V 3ERU lERV lt¼V 3ERW lERX lt½V 3ERY lERZ lt¾V 3ER[ lER\ lt¿V 3ER] lER^ ltÀV 3ER_ lER` ltÁV 3ERa lERb ltÂERcR/V 3ERd lERe lltÃV 3ERf lERg ltÄV 3ERh lERi ltÅERjR/V 3ERk lERl lltÆV 3ERm lERn ltÇERoRERpR/V 3ERq lERr lltÈV 3ERs lERt ltÉV 3ERu lERv ltÊV 3ERw lERx ltËV 3ERy lERz ltÌV 3ER{ lER| ltÍV 3ER} lER~ ltÎV 3ER lER€ ltÏV 3ER� lER‚ ltÐV 3ERƒ lER„ ltÑV 3ER… lER† ltÒV 3ER‡ lERˆ ltÓV 3ER‰ lERŠ ltÔV 3ER‹ lERŒ ltÕV 3ER� lERŽ ltÖER�R/V 3ER� lER‘ llt×V 3ER’ lER“ ltØV 3ER” lER• ltÙV 3ER– lER— ltÚV 3ER˜ lER™ ltÛV 3ERš lER› ltÜV 3ERœ lER� ltÝV 3ERž lERŸ ltÞV 3ER  lER¡ ltßV 3ER¢ lER£ ltàER¤táRltâV 3ER¥ lER¦ ltãERÎV 3ER§ lER¨ lltäV 3ER© lERª ltåV 3ER« lER¬ ltæV 3ER­ lER® ltçV 3ER¯ lER° ltèV 3ER± lER² ltéV 3ER³ lER´ ltêERÏV 3ERµ lER¶ lltë]UV 3ER· lER¸ l4       tìV 3ER¹ lERº ltíV 3ER» lER¼ ltî]gERÐV 3ER½ lER¾ ll4       tïV 3ER¿ ltðERÀtñV tòR# (Ñ  r¦  i@  zLBase class for platform adapters: connect/auth, receive, send, handle media.Fc                ó:   <€ V ^8„  d   QhRS[ RS[S[ ,          RR/# )r   rC  r   r   NrI  )r   rä  s   "€r   r   Ú BasePlatformAdapter.__annotate__I  s&   ø€ ÷ *ñ *¡sð *±(¹3µ-ð *ÀDñ *r   c                óŒ   € \        V R\        4      pV'       d   W#\        V4      &   R# VP                  \        V4      R4       R# )z±Set or clear (``None``) the live working-state phrase for a chat. In-memory only: the
next typing refresh renders it; a no-op store on adapters that never read
``_status_text``.Ú_status_textN)rÝ  r|   r8   Úpop)rë  rC  r   Ústores   &&& r   Úset_status_textÚ#BasePlatformAdapter.set_status_textI  s3   € ô ˜4 ´Ó6ˆßØ"&”#�g“,Óà�I‰I”c˜'“l DÖ)r   Tré  Nc                ó&   <€ V ^8„  d   QhRS[ RS[/# )r   Úconfigrq   )rm  rl  )r   rä  s   "€r   r   rà  q  s   ø€ ÷ C/ñ C/™~ð C/¹ñ C/r   c                ó¨  € Wn         W n        R V n        RV n        R V n        R V n        R V n        RRuV n        V n        R V n	        R V n
        R V n        \        4       V n        R;V n        V n        / V n        / V n        / V n        / V n        / V n        / V n        RV n        \.        V n        \2        V n        R V n        / V n        \        4       V n        / V n        \        4       V n        R V n         R V n!        R V n"        R V n#        RV n$        \        4       \        4       uV n%        V n&        \        4       V n'        \        4       V n(        / V n)        R # )NFTÚ	interrupt)*rè  rq   Ú_message_handlerÚ_no_message_handler_loggedÚ_reaction_handlerÚ_platform_event_handlerÚ_topic_recovery_fnÚ_runningÚ_fatal_error_retryableÚ_fatal_error_codeÚ_fatal_error_messageÚ_fatal_error_handlerr&  Ú_detached_fatal_tasksÚ_platform_lock_takeover_allowedÚ!_platform_lock_takeover_attemptedÚ_active_sessionsÚ_pending_messagesÚ_requeue_countsÚ_pending_text_batchesÚ_pending_text_batch_tasksÚ_session_tasksÚ_busy_text_modeÚ"DEFAULT_BUSY_TEXT_DEBOUNCE_SECONDSÚ_busy_text_debounce_secondsÚ"DEFAULT_BUSY_TEXT_HARD_CAP_SECONDSÚ_busy_text_hard_cap_secondsÚ_human_delay_range_msÚ_text_debounceÚ_background_tasksÚ_post_delivery_callbacksÚ_expected_cancelled_tasksÚ_busy_session_handlerÚ_owner_profileÚ_shared_listener_profileÚ_authorization_checkÚ_auto_tts_defaultÚ_auto_tts_enabled_chatsÚ_auto_tts_disabled_chatsÚ_streaming_tts_completed_turnsÚ_typing_pausedrâ  )rë  rè  rq   s   &&&r   Ú__init__ÚBasePlatformAdapter.__init__q  sW  € ØŒØ ŒØ:>ˆÔØ05ˆÔ'ØX\ˆÔàcgˆÔ$àLPˆÔØ5:¸DÐ2ˆŒ�tÔ2Ø04ˆÔØ37ˆÔ!ØgkˆÔ!ô
 +.«%ˆÔ"àX]Ð]ˆÔ,¨tÔ/Uð ;=ˆÔØ:<ˆÔð 02ˆÔØ>@ˆÔ"ØBDˆÔ&Ø79ˆÔð
 %0ˆÔÜ2TˆÔ(Ü2TˆÔ(ð AEˆÔ"Ø<>ˆÔä47³EˆÔð 9;ˆÔ%Ü<?»EˆÔ&Ø_cˆÔ"à-1ˆÔð 8<ˆÔ%àcgˆÔ!à',ˆÔÜFIÃeÌSËUÐCˆÔ$ dÔ&Cô
 9<»ˆÔ+ä#&£5ˆÔà,.ˆÖr   c                ó8   <€ V ^8„  d   QhRS[ S[.S[3,          /# rj   )rh  r8   r9   )r   rä  s   "€r   r   rà  ·  s   ø€ ÷ ñ ¡©#¨±¨Õ 4ñ r   c                ó   € \         # )z|Length function for message size; override where the platform counts
differently from ``len`` (Telegram: UTF-16 code units).rØ   r™  s   &r   Úmessage_len_fnÚ"BasePlatformAdapter.message_len_fn¶  s	   € ô ˆ
r   c                ó&   <€ V ^8„  d   QhRS[ RS[/# ©r   rC  r   r7   )r   rä  s   "€r   r   rà  ¼  s   ø€ ÷ añ a±3ð a¹3ñ ar   c                ó$   a € \        V 3R lR4      # )z¿Per-chat max length in ``message_len_fn_for_chat`` units: the adapter's
``MAX_MESSAGE_LENGTH`` (4096 when absent); the relay adapter overrides since it fronts N
platforms with different caps.c                  óD   <€ \        \        S R R4      ;'       g    R4      # )ÚMAX_MESSAGE_LENGTHé   )r9   ro   r™  s   €r   rš  ÚABasePlatformAdapter.max_message_length_for_chat.<locals>.<lambda>À  s   ø€ ¤3¤w¨tÐ5IÈ4Ó'P×'XÐ'XÐTXÔ#Yr   r  ©rw   ©rë  rC  s   f&r   Úmax_message_length_for_chatÚ/BasePlatformAdapter.max_message_length_for_chat¼  s   ø€ ô ÔYÐ[_Ó`Ð`r   c                ó>   <€ V ^8„  d   QhRS[ RS[S[ .S[3,          /# r  ©r8   rh  r9   )r   rä  s   "€r   r   rà  Â  s&   ø€ ÷ #ñ #©sð #±xÁÀÁsÀ
Õ7Kñ #r   c                ó   € V P                   # )z…Per-chat length function (companion to max_message_length_for_chat); the relay
adapter overrides it per the chat's fronting platform.)r  r  s   &&r   Úmessage_len_fn_for_chatÚ+BasePlatformAdapter.message_len_fn_for_chatÂ  s   € ð ×"Ñ"Ð"r   c                ó    <€ V ^8„  d   QhRS[ /# rj   rO  )r   rä  s   "€r   r   rà  È  s   ø€ ÷ ñ ©Dñ r   c                ó   € R# )ué  Whether this adapter enforces its own config-driven access policy at intake
(``dm_policy``/``group_policy``/``allow_from``: WeCom, Weixin, QQBot, WhatsAppâ€¦). The
gateway env allowlist runs *after* the adapter; without one it trusts this flag ONLY when
the effective policy is a real ``"allowlist"`` â€” never ``"open"`` (the default), which would
be a network-exposed fail-open (SECURITY.md Â§2.6). Open access still requires
``{PLATFORM}_ALLOW_ALL_USERS`` / ``GATEWAY_ALLOW_ALL_USERS``.Frt   r™  s   &r   Úenforces_own_access_policyÚ.BasePlatformAdapter.enforces_own_access_policyÇ  s   € ñ r   c                ó    <€ V ^8„  d   QhRS[ /# rj   rO  )r   rä  s   "€r   r   rà  Ò  s   ø€ ÷ ñ ©4ñ r   c                ó   € R# )uH  Whether inbound was already authorized by a TRUSTED UPSTREAM (relay only): the Team
Gateway connector authenticates the WebSocket and resolves owner-only author binding BEFORE
delivery, so the no-allowlist default-deny would be wrong. Authorization DELEGATED, not
ABSENT â€” every network-exposed direct adapter leaves it False.Frt   r™  s   &r   Úauthorization_is_upstreamÚ-BasePlatformAdapter.authorization_is_upstreamÑ  ó   € ñ r   c                óx   <€ V ^8„  d   QhRS[ S[,          RS[ S[S[S[3,          ,          RS[ S[,          RS[/# )r   rƒ   r�   rC  r   )rf  r8   r|   rg  rµ   )r   rä  s   "€r   r   rà  Ù  sB   ø€ ÷ ñ Ù!¡#�ðÙ9AÁ$ÁsÉCÀxÅ.Õ9Qðá™#•ðá*.ñr   c                ó   € R# )zïWhether native streaming-draft updates (``send_draft``) work for this chat type;
``chat_id`` lets the relay adapter answer per negotiated capabilities. Consumers
fall back to ``send`` + ``edit_message`` when False or ``send_draft`` raises.Frt   )rë  rƒ   r�   rC  s   &&&&r   Úsupports_draft_streamingÚ,BasePlatformAdapter.supports_draft_streamingÙ  r/  r   c                óR   <€ V ^8„  d   QhRS[ RS[S[S[ S[3,          ,          RS[/# )r   r  r�   r   )r8   rf  r|   rg  rµ   )r   rä  s   "€r   r   rà  á  s3   ø€ ÷ ñ ±Sð ÁHÉTÑRUÑWZÐRZÍ^ÕD\ð Ñhlñ r   c                ó   € R# )z©Whether the stream consumer should finalize with a *fresh* final message (best-effort
deleting the preview) instead of final-editing it (Telegram: keeps rich rendering).Frt   )rë  r  r�   s   &&&r   Úprefers_fresh_final_streamingÚ1BasePlatformAdapter.prefers_fresh_final_streamingá  ó   € ñ r   c                ó0   <€ V ^8„  d   QhRS[ S[,          /# rj   rœ  )r   rä  s   "€r   r   rà  æ  s   ø€ ÷ ñ ©(±3­-ñ r   c                ó   € R# )zîMax single-message length (``message_len_fn`` units) the stream consumer may
accumulate before splitting, for rich send/draft paths exceeding the legacy cap
(Telegram Rich Messages: 32,768 vs 4,096). ``None`` = use ``MAX_MESSAGE_LENGTH``.Nrt   r™  s   &r   Ústreaming_overflow_limitÚ,BasePlatformAdapter.streaming_overflow_limitæ  s   € ñ r   c                ó^   <€ V ^8„  d   QhRS[ RS[RS[ RS[S[S[ S[3,          ,          RS[/# )r   rC  Údraft_idr  r�   r   )r8   r9   rf  r|   rg  rI  )r   rä  s   "€r   r   rà  ì  sF   ø€ ÷ Zñ Z©ð Z±sð ZÁSð ZÙ#+©D±±c°­NÕ#;ðZÙGQñZr   c              ƒ  óL   "  € \        \        V 4      P                   R24      h5i)uc  Send or update an animated streaming-draft preview. Reuse one non-zero ``draft_id``
across a response so the platform animates (different responses need different ids). Drafts
have no message_id (no edit/reply/delete) â€” the final answer goes out as a regular ``send``.
Must be overridden by adapters returning True from :meth:`supports_draft_streaming`.z does not implement send_draft)ÚNotImplementedErrorÚtyperÎ  )rë  rC  r>  r  r�   s   &&&&&r   Ú
send_draftÚBasePlatformAdapter.send_draftì  s%   é € ô "¤T¨$£Z×%8Ñ%8Ð$9Ð9WÐ"XÓYÐYùrÃ  c                ó*   <€ V ^8„  d   QhRS[ RS[ RR/# )r   r–   Úsinkr   N©rg  )r   rä  s   "€r   r   rà  ÷  s"   ø€ ÷ 
+ñ 
+©#ð 
+±Sð 
+¸Tñ 
+r   c                óˆ  € ^ RI HpHpHp \	        W4      '       d0   VP
                  '       d   VP                  VP
                  4       R# \	        W4      '       d%   VP                  '       g   VP                  4        R# \	        W4      '       d2   VP
                  '       d   VP                  VP
                  4       R# R# R# )zƒRender a MessageChunk / MessageStop / Commentary onto the sink (a
GatewayStreamConsumer), mapping 1:1 onto its existing primitives.)ÚMessageChunkÚMessageStopÚ
CommentaryN)
Úgateway.stream_eventsrH  rI  rJ  r¤   r   Úon_deltaÚfinalÚon_segment_breakÚon_commentary)rë  r–   rE  rH  rI  rJ  s   &&&   r   Úrender_message_eventÚ(BasePlatformAdapter.render_message_event÷  sz   € ÷ 	PÑOÜ�e×*Ò*¨u¯z¯z¨zØ�M‰M˜%Ÿ*™*Ö%Ü˜×+Ò+°E·K·K°Kà×!Ñ!Ö#Ü˜×*Ò*¨u¯z¯z¨zØ×Ñ˜uŸz™zÖ*ñ 0:Ñ*r   rá  ÚallÚpreview_max_lenc          	      óB   <€ V ^8„  d   QhRS[ RS[RS[RS[S[,          /# )r   r–   rá  rS  r   )rg  r8   r9   rf  )r   rä  s   "€r   r   rà    s7   ø€ ÷ vñ v¡sð v±Sð vÑSVð vÑ`hÑilÕ`mñ vr   c          	     ór  € ^ RI Hp \        W4      '       g   R# ^ RIHpHpHp V! VP                  RR7      VP                  r˜VR8X  d`   VP                  '       dN   V! VP                  W0P                  4      p
\        RW‰\        VP                  P                  4       4      V
R7      # VP                  '       g   \        R	W‰R
7      # VR8X  d   \        RW‰VP                  R7      # V^ 8”  d   TM^(pV! VP                  VP                  VP                  VR7      p\        RW‰V P                  V4      R7      # )zðRendered chrome for a ToolCallChunk, or None to eat it (adapters without editing/rich
text override to None). ``mode``: tool-progress mode ("all"/"new"/"verbose");
``preview_max_len`` mirrors ``tool_preview_length`` (0 = no cap in verbose).)ÚToolCallChunkN)Úget_tool_emojiÚprepare_tool_previewÚverbose_tool_args_textu   âš™ï¸�)rv   Úverbosezgateway.progress.tool_verbose)ÚemojiÚtoolÚkeysÚargszgateway.progress.tool_pending)r[  r\  zgateway.progress.tool_preview)r[  r\  Úpreview)ÚfallbackÚmax_len)rK  rV  r¤   Úagent.displayrW  rX  rY  Ú	tool_namer^  Úsupports_code_blocksr   r$  r]  r_  Úformat_tool_preview)rë  r–   rá  rS  rV  rW  rX  rY  r[  r\  Úargs_strÚcapÚprepareds   &&$$         r   Úformat_tool_eventÚ%BasePlatformAdapter.format_tool_event  s  € õ 	8Ü˜%×/Ò/Ùß^Ñ^Ù$ U§_¡_¸hÔGÈÏÉˆtØ�9Ô §§ Ù-¨e¯j©j¸/×KdÑKdÓeˆHÜÐ4¸EÔSWÐX]×XbÑXb×XgÑXgÓXiÓSjÐqyÔzÐzØ�}�}ˆ}ÜÐ4¸EÔMÐMØ�9ÔÜÐ4¸EÐV[×VcÑVcÔdÐdà!0°1Ô!4‰o¸"ˆÙ'Ø�O‰O˜UŸZ™Z°%·-±-ÈôNˆäÐ0¸ÐRV×RjÑRjÐksÓRtÔuÐur   c                ó$   <€ V ^8„  d   QhRRRS[ /# )r   r_  r‰  r   rk   )r   rä  s   "€r   r   rà    s   ø€ ÷ ñ ¨=ð ¹Sñ r   c                ó   € VP                   # )z‹Platform-native formatting of a compact tool preview; rich-text adapters may use
the preview's metadata (e.g. a URL shortened for display).rž  )rë  r_  s   &&r   re  Ú'BasePlatformAdapter.format_tool_preview  s   € ð �|‰|Ðr   c                ó   € V P                   R J# r¼  ©ró  r™  s   &r   rš  ÚBasePlatformAdapter.<lambda>  s   € ¨D×,EÑ,EÈTÑ,Qr   c                ó   € V P                   # r¼  ro  r™  s   &r   rš  rp     s
   € °×0IÒ0Ir   c                ó   € V P                   # r¼  )rò  r™  s   &r   rš  rp  !  s
   € ¨T×-CÒ-Cr   c                ó   € V P                   # r¼  )rñ  r™  s   &r   rš  rp  "  s
   € °$×2MÒ2Mr   c                ó&   <€ V ^8„  d   QhRS[ RS[/# r  r´   )r   rä  s   "€r   r   rà  $  s   ø€ ÷ [ñ [±ð [¹ñ [r   c                ó„   € WP                   9   ;'       g,    WP                  9  ;'       d    \        V P                  4      # )u  Whether auto-TTS fires for ``chat_id``: explicit ``/voice on|tts`` wins,
then explicit ``/voice off``, then the global ``voice.auto_tts`` default.

Decision layers (Issue #16007): 1. Explicit ``/voice on`` or ``/voice tts`` â†’ always fire (even if
``voice.auto_tts`` is False). 2. 3.
)r  r  rµ   r  r  s   &&r   Ú_should_auto_tts_for_chatÚ-BasePlatformAdapter._should_auto_tts_for_chat$  sA   € ð ×6Ñ6Ñ6÷ [ð [Ø×8Ñ8Ñ8×YÐY¼TÀ$×BXÑBXÓ=Yð	[r   c                ó"   <€ V ^8„  d   QhRRRR/# )r   Úhandlerz7Callable[[BasePlatformAdapter], Awaitable[None] | None]r   Nrt   )r   rä  s   "€r   r   rà  .  s   ø€ ÷ ,ñ ,Ð/hð ,Ðmqñ ,r   c                ó   € Wn         R # r¼  )rô  ©rë  ry  s   &&r   Úset_fatal_error_handlerÚ+BasePlatformAdapter.set_fatal_error_handler.  s   € Ø$+Ö!r   z@connected but not yet confirmed active; recovering in backgroundc                ó    <€ V ^8„  d   QhRS[ /# rj   rO  )r   rä  s   "€r   r   rà  8  s   ø€ ÷ ñ ¡Dñ r   c                ó   € R# )z­True while connect() succeeded but delivery is not confirmed.

Adapters with a separately-proven receive path override this; the
default adapter is either connected or not.
Frt   r™  s   &r   Úsend_path_degradedÚ&BasePlatformAdapter.send_path_degraded7  s   € ñ r   Úlistener_basec                ó4   <€ V ^8„  d   QhRS[ S[,          RR/# )r   r‚  r   Nr"  )r   rä  s   "€r   r   rà  @  s#   ø€ ÷ gñ g±¹µð gÈñ gr   c          	     óÒ   € RV n         R;V n        V n        RV n        V P                  '       d   V P                  4        R# V'       d   RV/M/ pV P                  ! RRRRRRR/VB  R# )	a  ``listener_base`` (``http://host:port``) is stamped by port-binders after a REAL bind: under the
multiplexer it is the shared listener a served profile's ``/p/<profile>/`` mirror hangs off, and
what the dashboard/Desktop report as that profile's api_server/webhook URL.TNr‚  Ú	connectedÚplatform_stateÚ
error_codeÚerror_message)r…  )rð  rò  ró  rñ  r€  Ú_mark_degradedÚ_write_runtime_status_safe)rë  r‚  Úextras   &$ r   Ú_mark_connectedÚ#BasePlatformAdapter._mark_connected@  s|   € ð ˆŒØ=AÐAˆÔ Ô!:Ø&*ˆÔ#Ø×"×"Ð"Ø×ÑÖ!ç8E�_ mÑ4È2ˆEØ×+Ò+ñ gØ,7ðgØDHðgØX\ðgØ`eôgr   c                ó   <€ V ^8„  d   QhRR/# r‘   rt   )r   rä  s   "€r   r   rà  N  s   ø€ ÷ 
ñ 
 ñ 
r   c                óD   € V P                  RRRV P                  R7       R# )zKPublish ``retrying`` for a running adapter whose delivery path is unproven.Úconnected_degradedÚretryingN©r†  r‡  rˆ  )rŠ  ÚDEGRADED_STATUS_MESSAGEr™  s   &r   r‰  Ú"BasePlatformAdapter._mark_degradedN  s'   € à×'Ñ'Ø Ø%ØØ×6Ñ6ð	 	(ö 	
r   c                ó   <€ V ^8„  d   QhRR/# r‘   rt   )r   rä  s   "€r   r   rà  W  s   ø€ ÷ dñ d Dñ dr   c                óf   € R V n         V P                  '       g   V P                  RRRRR7       R# R# )FÚdisconnectedNr’  )rð  Úhas_fatal_errorrŠ  r™  s   &r   Ú_mark_disconnectedÚ&BasePlatformAdapter._mark_disconnectedW  s8   € ØˆŒØ×#×#Ð#Ø×+Ñ+Ø¨~È$Ð^bð ,ö dñ $r   c                ó0   <€ V ^8„  d   QhRS[ RS[ RS[RR/# )r   ÚcodeÚmessagerM  r   Nr´   )r   rä  s   "€r   r   rà  ]  s/   ø€ ÷ qñ q¡Sð q±3ð qÁdð qÈtñ qr   c               ód   € R V n         WuV n        V n        W0n        V P	                  RRWR7       R# )FÚfatalr’  N)rð  rò  ró  rñ  rŠ  )rë  rœ  r�  rM  s   &&&$r   Ú_set_fatal_errorÚ$BasePlatformAdapter._set_fatal_error]  s5   € ØˆŒØ<@Ð9ˆÔ Ô 9Ø&/Ô#Ø×'Ñ'¨ÀÐTXÐ'Öpr   c                ó$   <€ V ^8„  d   QhRS[ RR/# )r   Úcontextr   Nrk   )r   rä  s   "€r   r   rà  c  s   ø€ ÷ 3ñ 3±#ð 3ÀDñ 3r   c                ó   €  ^ RI Hp \        V RR4      ;'       g    V P                  P                  pV! R	RV/VB  R#   \
         d´   p\        T R\        4      pT P                  P                  T3T9  pTP                  T P                  P                  T34       T'       d   \        P                  M\        P                  ! RT'       d   RMR,           YP                  P                  T4        Rp?R# Rp?ii ; i)
zPPublish runtime status; log preparation failures without disrupting the adapter.)Úpublish_runtime_statusÚ_runtime_status_platform_keyNrq   Ú_status_write_loggedz.Failed to write runtime status (%s) for %s: %sz" (further failures at debug level)rn   rt   )Úgateway.statusr¥  ro   rq   rm   r[   rÝ  r&  Úaddr   rX   r«  )rë  r£  Úkwargsr¥  Úplatform_keyr   ÚloggedÚfirsts   &&,     r   rŠ  Ú.BasePlatformAdapter._write_runtime_status_safec  sÍ   € ð	3Ý=ô # 4Ð)GÈÓN×eÐeÐRV×R_ÑR_×ReÑReˆLÙ"ÑC¨LÐC¸FÔCøÜô 	3Ü Ð&<¼cÓBˆFØ—]‘]×(Ñ(¨'Ð2¸&Ñ@ˆEØ�J‰J˜Ÿ™×+Ñ+¨WÐ5Ô6ß$ŒV�^Š^¬&¯,©,Ð6Ø@×lqÑDhÐwyÕzØŸ™×,Ñ,¨c÷3ò 3ûð		3ús    ‚? œ!? ¿C=Á
BC8Ã$C8Ã8C=c                ó   <€ V ^8„  d   QhRR/# r‘   rt   )r   rä  s   "€r   r   rà  s  s   ø€ ÷ ñ ¨4ñ r   c              ƒ  óø  "  € V P                   pV'       g   R # V! V 4      p\        P                  ! V4      '       du   \        P                  ! V4      p\	        V R\
        4      pVP                  V4       VP                  VP                  4        \        P                  ! V4      G R j  x€L
  R # R #  L  \        P                   d.    TP                  4       '       g   TP                  \        4       h i ; i5i)Nrõ  )rô  r   ÚiscoroutineÚensure_futurerÝ  r&  r©  Úadd_done_callbackÚdiscardÚshieldÚCancelledErrorr  r   )rë  ry  re   r   Ú_taskss   &    r   Ú_notify_fatal_errorÚ'BasePlatformAdapter._notify_fatal_errors  sÃ   é € Ø×+Ñ+ˆßÙÙ˜“ˆÜ×Ò˜v×&Ò&ô ×(Ò(¨Ó0ˆDô   Ð&=¼sÓCˆFØ�J‰J�tÔØ×"Ñ" 6§>¡>Ô2ðÜ—n’n TÓ*×*Ò*ñ 'ñ +øÜ×)Ñ)ô à—y‘y—{’{Ø×*Ñ*Ô+NÔOØð	üs;   ‚:C:½AC:ÂB5 Â*B3Â+B5 Â/C:Â3B5 Â5*C7Ã C7Ã7C:c                ó2   <€ V ^8„  d   QhRS[ RS[ RS[ RS[/# )r   ÚscopeÚidentityÚresource_descr   r´   )r   rä  s   "€r   r   rà  Ž  s*   ø€ ÷ 3ñ 3©Cð 3¹3ð 3Ésð 3ÑW[ñ 3r   c                óî  € ^ RI HpHpHp ^ RIHp WuV n        V n        RV P                  P                  /p V! WVR7      w  ršT	'       d   R
# T P                  '       d›   T P                  '       g‰   \        T
\         4      '       ds   RT n        R
T n        T! T
4      pTeY   \"        P%                  RT P&                  Y<4       T! YTR7      w  ršT	'       d$   \"        P)                  RT P&                  Y<4       R
# \        T
\         4      '       d   T
P+                  R4      MRpT! T
4      pT'       d   RT R2MRpT'       d	   RT RT 2MTpT'       d   RT R2MRpT RT RT 2p\"        P-                  RT P&                  T4       T P                  T R2TR
R7       R#   T dM   pRT n        T P                  RT RTP                   R\        TP                  4       R	2R
R7        Rp?R# Rp?ii ; i)zêAcquire a scoped lock for this adapter; True on success. A live cross-HERMES_HOME
holder is replaced only when the runner armed this adapter for its initial
``--replace`` connect (the status module validates ownership and terminates).)Úacquire_scoped_lockÚscoped_lock_owner_labelÚtake_over_scoped_lock_holder)ÚScopedLockDirUnusablerq   ©r�   NÚlock_dir_unusablez2 lock cannot be taken: the gateway lock directory zO is not usable by this user (likely created by an elevated Hermes). To repair, z!; the gateway retries on its own.T)rM  FuK   [%s] %s was held by gateway PID %d â€” explicit --replace handoff completedz)[%s] Acquired %s after taking over PID %dÚpidz (PID rø  rn   z	 by the 'z' profile gatewayz+ Stop that gateway first (hermes --profile z gateway stop).z Stop the other gateway first.z already in userÃ   z[%s] %sÚ_lock)r¨  r¿  rÀ  rÁ  Úgateway.status_lock_dirrÂ  Ú_platform_lock_scopeÚ_platform_lock_identityrq   rm   r   rÕ  r   rö  r÷  r¤   r|   r   rX   rF  Úinfor¥   r   )rë  r»  r¼  r½  r¿  rÀ  rÁ  rÂ  Ú	lock_metaÚacquiredr   r   Ú	owner_pidÚowner_profileÚpid_partÚholderÚremedyr�  s   &&&&              r   Ú_acquire_platform_lockÚ*BasePlatformAdapter._acquire_platform_lockŽ  sü  € ÷ 	nÑmÝAØBGÐ?ˆÔ! 4Ô#?Ø §¡×!4Ñ!4Ð5ˆ	ð	Ù!4°UÈyÔ!YÑˆH÷ ÙØ×0×0Ð0¸×9_×9_Ð9_Ü˜x¬×.Ò.à38ˆDÔ0Ø59ˆDÔ2Ù4°XÓ>ˆIØÒ$Ü—‘ØaØ—I‘I˜}ô9ñ &9¸ÐS\Ô%]Ñ"�ßÜ—K‘KÐ KÈTÏYÉYÐXeÔqÙÜ+5°hÄ×+EÒ+E�H—L‘L Ô'È4ˆ	ñ 0°Ó9ˆß,5�V˜I˜; aÑ(¸2ˆßKX�9˜]˜OÐ+<¸X¸JÑGÐ^fˆç"ð @À¸ÈoÑ^Ø(Hð 	à"�O ?°6°(¸!¸F¸8ÐDˆÜ�‰�Y §	¡	¨7Ô3Ø×Ñ   u˜o¨wÀ$ÐÔGÙøðS %ô 	ð ,0ˆDÔ(Ø×!Ñ!Ø#Ø �/Ð!SÐTW×T`ÑT`ÐSað bZä& s§|¡|Ó4Ð5Ð5VðXð ð "ô  õ ûð	ús   ¸F! Æ!G4Æ(AG/Ç/G4c                ó   <€ V ^8„  d   QhRR/# r‘   rt   )r   rä  s   "€r   r   rà  Ã  s   ø€ ÷ ,ñ ,¨ñ ,r   c                ót   € \        V RR4      pV'       g   R# ^ RIHp V! V P                  V4       RV n        R# )z;Release the scoped lock acquired by _acquire_platform_lock.rÉ  N)Úrelease_scoped_lock)ro   Úgateway.status_scoped_locksrÖ  rÈ  rÉ  )rë  r¼  rÖ  s   &  r   Ú_release_platform_lockÚ*BasePlatformAdapter._release_platform_lockÃ  s2   € ä˜4Ð!:¸DÓAˆßÙÝCÙ˜D×5Ñ5°xÔ@Ø'+ˆÖ$r   c                ó$   <€ V ^8„  d   QhRS[ RR/# )r   Únativer   NrF  )r   rä  s   "€r   r   rà  Ò  s   ø€ ÷ 1ñ 1©Cð 1¸4ñ 1r   c           
     óê  €  ^ RI Hp V! 4       P                  \        V P                  R\        V P                  4      4      4      pT P                  TJg   T P                  f   Yn
        \        4       T n        T F~  w  rVT\        TRR4      ;'       g    \        T4      3pYpP                  9   d   K9   T! Y4       \        P                  RT P                  T4       T P                  P!                  T4       K€  	  R#   \         d-   p\        P                  RT P                  T4        Rp?R# Rp?ii ; i  \         d/   p\        P                  RT P                  TTRR	7        Rp?L�Rp?ii ; i)
a(  Invoke plugin-registered native handler factories (``ctx.register_platform_handler``)
with ``(native, adapter)``; adapters call this from ``connect()`` once the native
client exists and :meth:`rewire_plugin_handlers` re-runs it for plugins loaded later.
Idempotent per native client: a factory is keyed by ``(plugin, qualname)`` and skipped once
wired on this ``native`` (a force re-discovery hands back NEW function objects for the same
plugin, so identity alone would double-register). Each factory is isolated so a bad plugin
can't block connecting.)Úget_plugin_managerrm   z0[%s] Could not load plugin handler factories: %sNrÏ  z+[%s] Wired native handlers from plugin '%s'z+[%s] Plugin '%s' handler factory raised: %sTr   )Úhermes_cli.pluginsrÝ  Úget_platform_handler_factoriesro   rq   r8   r[   r   rX   rF  Ú_plugin_handler_nativeÚ_plugin_handlers_wiredr&  ÚreprrÊ  r   r©  )	rë  rÛ  rÝ  Ú	factoriesr  rÚ  Úplugin_namer  r   s	   &&       r   Ú_wire_plugin_handlersÚ)BasePlatformAdapter._wire_plugin_handlersÒ  s9  € ð	Ý=Ù*Ó,×KÑKÜ˜Ÿ™ w´°D·M±MÓ0BÓCóEˆIð
 ×&Ñ&¨fÓ4¸×8SÑ8SÒ8[à*0Ô'Ü*-«%ˆDÔ'Û$-Ñ ˆGØ¤¨°ÀÓ F× WÐ WÌ$ÈwË-ÐXˆCØ×1Ñ1Ô1Ùð1Ù˜Ô%Ü—‘ÐIÈ4Ï9É9ÐVaÔbð
 ×'Ñ'×+Ñ+¨CÖ0ó %.øô ô 	Ü�N‰NÐMÈtÏyÉyÐZ[Ô\Ýûð	ûô ô 1Ü—‘ÐJÈDÏIÉIÐWbØ ¨4ð ÷ 1ñ 1ûð1ús0   ‚AC? Â5)D9Ã?D6Ä
!D1Ä1D6Ä9E2Å$E-Å-E2c                ó   <€ V ^8„  d   QhRR/# r‘   rt   )r   rä  s   "€r   r   rà  ò  s   ø€ ÷ @ñ @¨ñ @r   c                ó\   € V P                   f   R# V P                  V P                  4       R# )u˜  Register handlers of plugins loaded AFTER ``connect()`` wired the first batch (#87770);
the gateway runner calls this on every plugin-loaded event. Safe to call repeatedly: only
factories not yet wired on the live native client run. Before ``connect()`` has wired once
there is nothing to re-wire â€” connect will pick everything up. Adapters with extra plugin
registries (Slack action handlers) extend this.N)rá  rå  rà  r™  s   &r   Úrewire_plugin_handlersÚ*BasePlatformAdapter.rewire_plugin_handlersò  s'   € ð ×&Ñ&Ò.ÙØ×"Ñ" 4×#>Ñ#>Ö?r   c                ó    <€ V ^8„  d   QhRS[ /# rj   rk   )r   rä  s   "€r   r   rà  ý  s   ø€ ÷ +ñ +‘cñ +r   c                óJ   € V P                   P                  P                  4       # )z%Human-readable name for this adapter.)rq   rm   Útitler™  s   &r   rF  ÚBasePlatformAdapter.nameü  s   € ð �}‰}×"Ñ"×(Ñ(Ó*Ð*r   c                ó    <€ V ^8„  d   QhRS[ /# rj   rO  )r   rä  s   "€r   r   rà  	  s   ø€ ÷ ñ ™dñ r   c                ó   € V P                   # )z(Check if adapter is currently connected.)rð  r™  s   &r   Úis_connectedÚ BasePlatformAdapter.is_connected	  s   € ð �}‰}Ðr   c                ó$   <€ V ^8„  d   QhRS[ RR/# ©r   ry  r   N)ÚMessageHandler)r   rä  s   "€r   r   rà  	  s   ø€ ÷ (ñ (©>ð (¸dñ (r   c                ó   € Wn         R# )zISet the incoming-message handler (MessageEvent -> optional response str).N)rë  r{  s   &&r   Úset_message_handlerÚ'BasePlatformAdapter.set_message_handler	  s   € à 'Ör   c                ót   <€ V ^8„  d   QhRS[ S[S[S[S[3,          S[.S[R,          3,          ,          RR/# ©r   ry  Nr   ©rf  rh  r|   r8   rg  ri  )r   rä  s   "€r   r   rà  
	  s=   ø€ ÷ /ñ /Ù¡©$©s±C¨x­.¹#Ð)>Á	È$ÅÐ)OÕ PÕQð/ØVZñ/r   c                ó   € Wn         R# )z·Install the gateway-owned normalized platform-event boundary (stable dicts + internal
``SessionSource``); the runner owns authorization and plugin dispatch: no callback = fail
closed.N)rî  r{  s   &&r   Úset_platform_event_handlerÚ.BasePlatformAdapter.set_platform_event_handler
	  s
   € ð
 (/Ö$r   c                ó\   <€ V ^8„  d   QhRS[ S[S[.S[ S[,          3,          ,          RR/# )r   Úfnr   N)rf  rh  rg  r8   )r   rä  s   "€r   r   rà  	  s1   ø€ ÷ %ñ %©±¹3¸%ÁÉ#ÅÐ:NÕ1OÕ(Pð %ÐUYñ %r   c                ó   € Wn         R# )z´Install a thread_id-recovery hook (Telegram DM topic mode): called with ``event.source``
before session keying; a non-None return replaces ``source.thread_id``. ``None`` clears
it.N)rï  )rë  r   s   &&r   Úset_topic_recovery_fnÚ)BasePlatformAdapter.set_topic_recovery_fn	  s
   € ð #%Ör   c                ó$   <€ V ^8„  d   QhRS[ RR/# r/  r0  )r   rä  s   "€r   r   rà  	  s   ø€ ÷ Iñ I©<ð I¸Dñ Ir   c                óª  € \        V RR4      p\        VRR4      pVe   Vf   R#  V! V4      pVe.   \        V4      \        VP                  ;'       g    R4      8X  d   R#   ^ RIHp T! T\        T4      R	7      Tn        R#   \         d    \        P                  RRR7        R# i ; i  \         d    \        P                  R
RR7        R# i ; i)zDRewrite ``event.source.thread_id`` in place if the hook returns one.rï  NrŒ   rn   ztopic recovery hook failedTr   )Úreplace_source)r~   ztopic recovery rewrite failed)	ro   r8   r~   r[   r   r«  Úgateway.session_identityr  rŒ   )rë  r–   ÚrecoverrŒ   Ú	recoveredr  s   &&    r   Ú_apply_topic_recoveryÚ)BasePlatformAdapter._apply_topic_recovery	  sÉ   € ä˜$Ð 4°dÓ;ˆÜ˜ ¨$Ó/ˆØŠ?˜fšnÙð	Ù ›ˆIØÒ ¤C¨	£N´c¸&×:JÑ:J×:PÐ:PÈbÓ6QÔ$QÙð %Rð
	IÝ?Ù)¨&¼CÀ	»NÔKˆEŽLøô ô 	Ü�L‰LÐ5ÀˆLÔEÚð	ûô ô 	IÜ�L‰LÐ8À4ˆL×Hð	Iús)   ¦-B ÁB Á#B, Â"B)Â(B)Â,"CÃCc                ó`   <€ V ^8„  d   QhRS[ S[S[S[.S[S[,          3,          ,          RR/# rô  )rf  rh  rz  r8   ri  rµ   )r   rä  s   "€r   r   rà  *	  s8   ø€ ÷ -ñ -±¹Á<ÑQTÐBUÑW`ÑaeÕWfÐBfÕ9gÕ0hð -Ðmqñ -r   c                ó   € Wn         R# )zESet an optional handler for messages arriving during active sessions.N)r  r{  s   &&r   Úset_busy_session_handlerÚ,BasePlatformAdapter.set_busy_session_handler*	  s   € à%,Ö"r   c                óp   <€ V ^8„  d   QhRS[ S[S[S[S[3,          .S[R,          3,          ,          RR/# rú  rû  )r   rä  s   "€r   r   rà  .	  s=   ø€ ÷ )ñ )©H±X¹tÁCÉÀH½~Ð>NÑPYÐZ^ÕP_Ð>_Õ5`Õ,að )Ðfjñ )r   c                ó   € Wn         R# )a  Set the handler for platform-native emoji-reaction events: a normalised dict
(``platform``, ``event_name`` "reaction:added"/"reaction:removed", ``reaction``,
``user_id``, ``item_user_id``, ``channel_id``, ``message_ts``, ``event_ts``, ``raw_event``)
fanned out via ``HookRegistry.emit``.N)rí  r{  s   &&r   Úset_reaction_handlerÚ(BasePlatformAdapter.set_reaction_handler.	  s
   € ð
 ")Ör   c                ót   <€ V ^8„  d   QhRS[ S[S[S[ S[,          S[ S[,          .S[3,          ,          RR/# )r   Úcallbackr   N)rf  rh  r8   rµ   )r   rä  s   "€r   r   rà  5	  s;   ø€ ÷ -ñ -Ù ¡©3±¹µ¹xÉ½}Ð*MÉtÐ*SÕ!TÕUð-ØZ^ñ-r   c                ó   € Wn         R# )z­Register ``(user_id, chat_type, chat_id) -> bool``; adapters pulling external context
(Slack thread replies) use it to flag non-allowlisted senders as unverified background.N)r  )rë  r  s   &&r   Úset_authorization_checkÚ+BasePlatformAdapter.set_authorization_check5	  s
   € ð %-Ö!r   Úis_botr~   c                óŽ   <€ V ^8„  d   QhRS[ S[,          RS[ S[,          RS[ S[,          RS[RS[ S[,          RS[ S[,          /# )r   Úuser_idrƒ   rC  r  r~   r   ©rf  r8   rµ   )r   rä  s   "€r   r   rà  ;	  sP   ø€ ÷ ñ ©X±c­]ð ÁxÑPSÅ}ð Ù'/±¥}ðÙHLðá)1±#­ðáBJÉ4Å.ñr   c               ó~  € V'       d   V P                   f   R# / pV'       d   RVR&   Ve   WVR&    V P                   ! WV3/ VB pTRJ g   TRJ d   T# \        P                  RT P                  \        T4      P                  T4       R#   \         d(    \        P                  RT P                  TRR7        R# i ; i)	aS  True/False from the registered check, or None when no check exists ("trust unknown",
legacy). ``is_bot``/``thread_id`` are forwarded as keywords only when set so legacy
three-positional callbacks keep working. Only literal booleans propagate: a truthy
non-boolean is "unknown", never an authorization that gates a credentialed side effect.NTr  r~   z@[%s] Authorization check raised for user %s; treating as unknownr   FzE[%s] Authorization check returned %s for user %s; treating as unknown)r  r[   r   rX   rF  rA  rÎ  )rë  r  rƒ   rC  r  r~   r‹  re   s   &&&&$$  r   Ú_is_sender_authorizedÚ)BasePlatformAdapter._is_sender_authorized;	  s¿   € ÷ ˜$×3Ñ3Ò;ÙØ "ˆßØ"ˆE�(‰OØÒ Ø!*�+Ñð	Ø×.Ò.¨wÀ7ÑTÈeÑTˆFð
 �T‹>˜V u›_ØˆMÜ�‰Ð^Ø—y‘y¤$ v£,×"7Ñ"7¸ô	Báøô ô 	Ü�N‰NÐ]ØŸ9™9 g¸ð ô >âð	ús   ±B
 Â
.B<Â;B<c                ó$   <€ V ^8„  d   QhRS[ RR/# )r   Úsession_storer   NrF  )r   rä  s   "€r   r   rà  U	  s   ø€ ÷ ,ñ ,©sð ,°tñ ,r   c                ó   € Wn         R# )zlSet the session store (e.g. Slack checks for an active thread session
before handling un-mentioned replies).N)Ú_session_store)rë  r!  s   &&r   Úset_session_storeÚ%BasePlatformAdapter.set_session_storeU	  s
   € ð ,Ör   c                ó4   <€ V ^8„  d   QhRS[ S[,          RR/# )r   Úprofile_namer   Nr"  )r   rä  s   "€r   r   rà  Z	  s#   ø€ ÷ lñ l©h±s­mð lÀñ lr   c                ó|   € T;'       g    RP                  4       ;'       g    R;pR8X  d
   RV n        R# TV n        R# )z‘Declare the owning multiplex profile (secondary profiles only); read by
:meth:`_session_key_profile` so adapter-level keys leave ``agent:main:``.rn   Nrv   )r‹   r	  )rë  r'  rF  s   && r   Úset_owner_profileÚ%BasePlatformAdapter.set_owner_profileZ	  s:   € ð 1=×0BÐ0BÀ×/IÑ/IÓ/K×/SÐ/SÈtÐ'S tÐXaÔ&a˜dˆÖÐgkˆÖr   c                ó0   <€ V ^8„  d   QhRS[ S[,          /# rj   r"  )r   rä  s   "€r   r   rà  _	  s   ø€ ÷ Kñ K©(±3­-ñ Kr   c                ó|   € \        V RR4      p\        V\        4      '       d   VP                  4       '       d   V# R# )z¨Transport profile for :func:`resolve_identity`: the owner name, or ``None`` = derive it
from the registry (the primary's identity then spells ``"default"`` out itself).r	  N)ro   r¤   r8   r‹   )rë  Úowners   & r   Ú_owner_transport_profileÚ,BasePlatformAdapter._owner_transport_profile_	  s4   € ô ˜Ð.°Ó5ˆÜ" 5¬#×.Ò.°5·;±;·=²=ˆuÐJÀdÐJr   c                ó0   <€ V ^8„  d   QhRS[ S[,          /# ©r   rŒ   ©rf  r€  )r   rä  s   "€r   r   rà  e	  s   ø€ ÷ ñ ¡H©]Õ$;ñ r   c                ó2  € Vf   R# ^ RI HpHp V! V4      pVe   V# \        V RR4      pVe   \	        \        VRR4      4      '       g   R#  V! WW P                  4       R7      #   \         d'    \        P                  RT P                  RR7        R# i ; i)	aÀ  Pin the source's :class:`RoutingIdentity` before anything derives a key from it. Every
ingress path (fresh event, batch merge, busy path, control command, callback) calls this
FIRST. Returns the identity, or ``None`` when it cannot be resolved (a rejected route under
multiplexing marks ``source.profile_route_rejected``; ``_drop_unresolved`` reads it) or when
no runner seam exists (hand-built adapters, restored sources: the legacy readers stay).N)Úcanonical_identityÚidentity_ofÚgateway_runnerÚ_transport_owner)ÚrunnerÚadapterÚtransport_profilez9[%s] identity resolution failed; using legacy key readersTr   )
r  r4  r5  ro   Úcallabler.  r[   r   r«  rF  )rë  rŒ   r4  r5  r¼  r8  s   &&    r   Ú_canonicalizeÚ!BasePlatformAdapter._canonicalizee	  s    € ð Š>ÙßLÙ˜vÓ&ˆØÒØˆOÜ˜Ð/°Ó6ˆØŠ>¤¬'°&Ð:LÈdÓ*S×!TÒ!TÙð	Ù%Ø¨t×GdÑGdÓGfôhð høäô 	ô �L‰LÐTÐVZ×V_ÑV_ÐjnˆLÔoÚð		ús   ÁA% Á%-BÂBc                ó&   <€ V ^8„  d   QhRS[ RS[/# ©r   r–   r   ©rz  rµ   )r   rä  s   "€r   r   rà  }	  s   ø€ ÷ ñ ¡lð ±tñ r   c                óŒ   € \        VRR4      pV P                  V4      e   R# \        VRR4      RJd   R# ^ RIHp V! W4       R# )uÛ   True when *event* must be dropped: its identity could not be resolved because the route
targets an unserved profile. Same disposition as the runner's ingress gate â€” one WARNING,
never a fall-through to ``agent:main``.rŒ   NFÚprofile_route_rejectedT)Údrop_rejected_route)ro   r<  Úgateway.parked_route_refusalrC  )rë  r–   rŒ   rC  s   &&  r   Ú_drop_unresolvedÚ$BasePlatformAdapter._drop_unresolved}	  sI   € ô ˜ ¨$Ó/ˆØ×Ñ˜fÓ%Ò1ÙÜ�6Ð3°UÓ;À4ÓGÙÝDÙ˜DÔ)Ùr   c                óF   <€ V ^8„  d   QhRS[ S[,          RS[ S[,          /# ©r   rŒ   r   )rf  rg  r8   )r   rä  s   "€r   r   rà  Š	  s'   ø€ ÷ Tñ T©8±C­=ð TÁHÉSÅMñ Tr   c                óô  € ^ RI Hp V! V4      pVe   VP                  # Ve   \        VRR4      MR\        V RR4      3 F5  p\	        V\
        4      '       g   K  VP                  4       '       g   K3  Vu # 	  \        V RR4      pV'       d   \        VRR4      MRp\        V4      '       g   R#  V! V4      p\	        T\
        4      '       d   TP                  4       '       d   T# R#   \         d     R# i ; i)u‚  Profile namespace for an adapter-derived session key. Ingress runs BEFORE the runner
stamps ``source.profile``, so without this every bot in a multiplexed gateway shares one
``agent:main:`` lane. Order: pinned ``RoutingIdentity`` â†’ ``source.profile`` â†’
``_owner_profile`` â†’ session-store resolver; getattr-guarded (object.__new__ in tests),
type-checked (no MagicMock in the key).)r5  Nr‰   r	  r#  Ú_resolve_profile_for_key)	r  r5  Úsession_key_profilero   r¤   r8   r‹   r;  r[   )rë  rŒ   r5  r¼  r)  rä  Úresolverrú   s   &&      r   Ú_session_key_profileÚ(BasePlatformAdapter._session_key_profileŠ	  së   € õ 	9Ù˜vÓ&ˆØÒØ×/Ñ/Ð/à06Ò0BŒG�F˜I tÔ,ÈÜ�DÐ*¨DÓ1ó3ˆIô ˜)¤S×)Ô)¨i¯o©o×.?Ô.?Ø Ò ñ	3ô
 ˜Ð.°Ó5ˆßGL”7˜5Ð"<¸dÔCÐRVˆÜ˜×!Ò!Ùð	Ù Ó'ˆHô & h´×4Ò4¸¿¹×9IÒ9IˆxÐSÈtÐSøô ô 	Úð	ús   Â0C( Ã(C7Ã6C7i   r¬  g333333Ó?ç       @rx   g      @Ú	min_valueÚ	max_valuec          
      óH   <€ V ^8„  d   QhRS[ RS[RS[RS[S[,          RS[/# )r   r  rv   rP  rQ  r   )r8   r¨  rf  )r   rä  s   "€r   r   rà  ´	  s<   ø€ ÷ ñ ¡sð ±Uð É%ð ÑbjÑkpÕbqð ñ  ~Cñ r   c               óz  € \        V P                  RR4      ;'       g    / p \        VP                  V4      4      p\        P                  ! V4      '       d   V^ 8  d   \        V4      p\        Wc4      pVe    Wd8”  d   \        P                  RWV4       TpV#   \        \
        3 d    \        T4      p L|i ; i)uq   Float from ``config.extra``; NaN/Inf/negative/unparseable â†’ ``default``; clamped to ``[min_value, max_value]``.r‹  Nz%%s=%s exceeds the %s ceiling; clamped)ro   rè  r¨  r¥   rž  rñ   ÚmathÚisfiniter¯  r   rX   )rë  r  rv   rP  rQ  r‹  rð  s   &&&$$  r   Ú_coerce_float_extraÚ'BasePlatformAdapter._coerce_float_extra´	  s£   € ä˜Ÿ™ W¨dÓ3×9Ð9°rˆð	$Ü˜5Ÿ9™9 S›>Ó*ˆFô �}Š}˜V×$Ò$¨°¬
Ü˜7“^ˆFÜ�VÓ'ˆØÒ  VÔ%7Ü�N‰NÐBÀCÐQZÔ[ØˆFØˆøô œ:Ð&ô 	$Ü˜7“^ŠFð	$ús   £B ÂB:Â9B:c                ó   <€ V ^8„  d   QhRR/# r‘   rt   )r   rä  s   "€r   r   rà  Ã	  s   ø€ ÷ dñ d¨dñ dr   c                óÐ   € V P                  RV P                  V P                  R7      V n        V P                  RV P                  V P                  V P
                  R7      V n        R# )zsRead ``text_batch_delay_seconds`` / ``text_batch_split_delay_seconds`` from ``config.extra`` at the shared cadence.Útext_batch_delay_seconds)rQ  Útext_batch_split_delay_seconds)rP  rQ  N)rV  Ú_TEXT_BATCH_DEFAULT_DELAY_SÚ_TEXT_BATCH_MAX_DELAY_SÚ_text_batch_delay_secondsÚ!_TEXT_BATCH_DEFAULT_SPLIT_DELAY_SÚ_TEXT_BATCH_MAX_SPLIT_DELAY_SÚ_text_batch_split_delay_secondsr™  s   &r   Ú_configure_text_batch_delaysÚ0BasePlatformAdapter._configure_text_batch_delaysÃ	  sf   € à)-×)AÑ)AØ&¨×(HÑ(HÐTX×TpÑTpð *Bó *rˆÔ&à/3×/GÑ/GØ,¨d×.TÑ.TØ×4Ñ4À×@bÑ@bð 0Hó 0dˆÖ,r   c                ó&   <€ V ^8„  d   QhRS[ RS[/# r?  ©rz  r8   )r   rä  s   "€r   r   rà  Ë	  s   ø€ ÷ 6ñ 6©ð 6¹ñ 6r   c                ó8   € V P                  VP                  4      # )zOAdapter-level session key for ``event``, profile-namespaced like the agent run.)Ú_source_session_keyrŒ   ©rë  r–   s   &&r   Ú_event_session_keyÚ&BasePlatformAdapter._event_session_keyË	  s   € à×'Ñ'¨¯©Ó5Ð5r   c                ó&   <€ V ^8„  d   QhRS[ RS[/# rH  )r€  r8   )r   rä  s   "€r   r   rà  Ï	  s   ø€ ÷ 7ñ 7©-ð 7¹Cñ 7r   c                óÊ   € V P                  V4       V P                  P                  p\        WP	                  R R4      VP	                  RR4      V P                  V4      R7      # )Úgroup_sessions_per_userTÚthread_sessions_per_userF)rm  rn  r‰   )r<  rè  r‹  r�  r¥   rM  )rë  rŒ   r‹  s   && r   rg  Ú'BasePlatformAdapter._source_session_keyÏ	  sY   € Ø×Ñ˜6Ô"Ø—‘×!Ñ!ˆÜ Ø¯I©IÐ6OÐQUÓ,VØ%*§Y¡YÐ/IÈ5Ó%QØ×-Ñ-¨fÓ5ô7ð 	7r   c                ó&   <€ V ^8„  d   QhRS[ RS[/# r?  re  )r   rä  s   "€r   r   rà  ×	  s   ø€ ÷ .ñ .¡\ð .±cñ .r   c                ó$   € V P                  V4      # )z?Session-scoped key for text batching (subclasses may override).)ri  rh  s   &&r   Ú_text_batch_keyÚ#BasePlatformAdapter._text_batch_key×	  s   € à×&Ñ& uÓ-Ð-r   c                ó$   <€ V ^8„  d   QhRS[ RR/# r/  r0  )r   rä  s   "€r   r   rà  Û	  s   ø€ ÷ _ñ _©ð _¸$ñ _r   c                ó@  € V P                  V4      '       d   R# V P                  V4      pV P                  P                  V4      pVf   T;q0P                  V&   M¤VP                  '       d&   \        VP                  VP                  4      Vn        VP                  '       dK   VP                  P                  VP                  4       VP                  P                  VP                  4       VP                  V4       \        VP                  ;'       g    R4      Vn        V P                  P                  V4      pV'       d'   VP                  4       '       g   VP                  4        \        P                   ! V P#                  V4      4      V P                  V&   R# )zMBuffer a text event (merging into a pending one) and restart the flush timer.Nrn   )rE  rr  rû  r¥   r   r$  r§  r“  r®  r°  rÒ   Ú_last_chunk_lenrü  r  r  r   Úcreate_taskÚ_flush_text_batch)rë  r–   r  r   Ú
prior_tasks   &&   r   Ú_enqueue_text_eventÚ'BasePlatformAdapter._enqueue_text_eventÛ	  s3  € à× Ñ  ×'Ò'ÙØ×"Ñ" 5Ó)ˆØ×-Ñ-×1Ñ1°#Ó6ˆØÒØ9>Ð>ˆH×1Ñ1°#Ò6à�z�zˆzÜ ,¨X¯]©]¸E¿J¹JÓ G�”Ø××ÐØ×#Ñ#×*Ñ*¨5×+;Ñ+;Ô<Ø×$Ñ$×+Ñ+¨E×,=Ñ,=Ô>Ø×*Ñ*¨5Ô1Ü#& u§z¡z×'7Ð'7°RÓ#8ˆÔ Ø×3Ñ3×7Ñ7¸Ó<ˆ
ß˜jŸo™o×/Ò/Ø×ÑÔÜ.5×.AÒ.AÀ$×BXÑBXÐY\ÓB]Ó.^ˆ×&Ñ& sÓ+r   c                ó6   <€ V ^8„  d   QhRS[ S[,          RS[/# )r   Úpendingr   )rf  rz  r¨  )r   rä  s   "€r   r   rà  ð	  s$   ø€ ÷ }ñ }©X±lÕ-Cð }Éñ }r   c                óx   € Ve   \        VR^ 4      M^ pW P                  8¼  d   V P                  # V P                  # )zMQuiet period before ``pending`` is dispatched; near-split chunks wait longer.rv  )ro   Ú_SPLIT_THRESHOLDra  r^  )rë  r}  Úlast_lens   && r   Ú_text_batch_delay_forÚ)BasePlatformAdapter._text_batch_delay_forð	  s<   € à=DÒ=P”7˜7Ð$5°qÔ9ÐVWˆØ7?×CXÑCXÔ7Xˆt×3Ñ3Ð|Ð^b×^|Ñ^|Ð|r   c                ó6   <€ V ^8„  d   QhRS[ RS[S[,          /# )r   r  r   ©r8   rf  rz  )r   rä  s   "€r   r   rà  õ	  s    ø€ ÷ 9ñ 9¡3ð 9©8±LÕ+Añ 9r   c                ó:   € V P                   P                  VR4      # )zURemove and return the pending batch for ``key`` (adapters with side tables override).N)rû  rã  )rë  r  s   &&r   Ú_pop_text_batchÚ#BasePlatformAdapter._pop_text_batchõ	  s   € à×)Ñ)×-Ñ-¨c°4Ó8Ð8r   c                ó$   <€ V ^8„  d   QhRS[ RR/# r/  r0  )r   rä  s   "€r   r   rà  ù	  s   ø€ ÷ )ñ )±ð )Àñ )r   c              ƒ  óD   "  € V P                  V4      G Rj  x€L
  R#  L5i)zNHand a flushed batch to the pipeline (adapters with per-chat guards override).N)Úhandle_messagerh  s   &&r   Ú_dispatch_text_batchÚ(BasePlatformAdapter._dispatch_text_batchù	  s   é € à×!Ñ! %Ó(×(Ô(ùs   ‚ —˜ c                ó$   <€ V ^8„  d   QhRS[ RR/# ©r   r  r   Nrk   )r   rä  s   "€r   r   rà  ý	  s   ø€ ÷ 3ñ 3©sð 3°tñ 3r   c              ƒ  ór   "  € V P                  V4      pVe   V P                  V4      G Rj  x€L
  R# R#  L5i)zEDispatch the pending batch for ``key`` immediately (no quiet period).N)r†  r‹  )rë  r  r–   s   && r   Ú_flush_text_batch_nowÚ)BasePlatformAdapter._flush_text_batch_nowý	  s7   é € à×$Ñ$ SÓ)ˆØÒØ×+Ñ+¨EÓ2×2Ò2ñ Ù2ùs   ‚*7¬5­	7c                ó$   <€ V ^8„  d   QhRS[ RR/# rŽ  rk   )r   rä  s   "€r   r   rà  
  s   ø€ ÷ >ñ >©3ð >°4ñ >r   c           	   ƒ  óL  "  € \         P                  ! 4       p \         P                  ! V P                  V P                  P                  V4      4      4      G Rj  x€L
  V P                  P                  V4      pVeF   W2JdA    V P                  P                  V4      VJ d   V P                  P                  VR4       R# R# V P                  V4      pVfA    V P                  P                  V4      VJ d   V P                  P                  VR4       R# R# \        P                  RV P                  T\        VP                  ;'       g    R4      4       \         P                  ! V P                  V4      4      G Rj  x€L
  V P                  P                  V4      VJ d   V P                  P                  VR4       R# R#  ELi LF  \         P                    d     L[i ; i  T P                  P                  T4      TJ d   T P                  P                  TR4       i i ; i5i)uz  Wait for the quiet period, then dispatch the batch for ``key``.

Two races share this body. (1) ``_enqueue_text_event`` cancels the prior flush task
on each new chunk; when ``Task.cancel()`` lands after ``sleep()`` already completed,
CancelledError is delivered at the *next* await â€” after a superseded task would have
popped the event, so the successor finds nothing and the message is lost. The identity
check therefore runs synchronously between the sleep and the pop. (2) A cancel that
lands while the dispatch is in flight would abort the agent turn (#12444), so the
dispatch is shielded and the outer CancelledError swallowed.Nz&[%s] Flushing text batch %s (%d chars)rn   )r   Úcurrent_taskr  r�  rû  r¥   rü  rã  r†  r   rÊ  rF  rÒ   r   rµ  r‹  r¶  )rë  r  r”  r-  r–   s   &&   r   rx  Ú%BasePlatformAdapter._flush_text_batch
  sÓ  é € ô ×+Ò+Ó-ˆð	>Ü—-’- × :Ñ :¸4×;UÑ;U×;YÑ;YÐZ]Ó;^Ó _Ó`×`Ð`Ø×2Ñ2×6Ñ6°sÓ;ˆEØÒ  UÓ%>Øð ×-Ñ-×1Ñ1°#Ó6¸,ÓFØ×.Ñ.×2Ñ2°3¸Ö=ñ Gð ×(Ñ(¨Ó-ˆEØŠ}Øð ×-Ñ-×1Ñ1°#Ó6¸,ÓFØ×.Ñ.×2Ñ2°3¸Ö=ñ Gô �K‰KÐ@À$Ç)Á)ÈSÔRUÐV[×V`ÑV`×VfÐVfÐdfÓRgÔhÜ—.’. ×!:Ñ!:¸5Ó!AÓB×BÐBð ×-Ñ-×1Ñ1°#Ó6¸,ÓFØ×.Ñ.×2Ñ2°3¸Ö=ñ Gò añ CøÜ×%Ñ%ô 	Ùð	ûð ×-Ñ-×1Ñ1°#Ó6¸,ÓFØ×.Ñ.×2Ñ2°3¸Õ=ð Güsw   ‚H$™AG ÁGÁ(G Â?H$ÃG Ã?H$Ä3G Å3G Å?GÆ G Æ?H$ÇG ÇG ÇG ÇG# ÇG Ç G# Ç#>H!È!H$c                ó6   <€ V ^8„  d   QhRS[ RS[S[,          /# rù  ©r8   rf  r&  )r   rä  s   "€r   r   rà  
  s   ø€ ÷ $5ñ $5¹Cð $5ÁHÉSÅMñ $5r   c                óV  a	€ \        V RR4      pV'       g   R#  \        VRR4      p\        V4      '       d	   V! V4      MRpTP                  T;'       g    T4      pT'       g   R# \        T4      o	\        T	3R l\        \        S	4      ^,
          RR4       4       R4      pTe   S	RT o	M1\        R \        S	4       4       R4      pTe   S	P                  T4       S	'       g   R# ^ RIHp T! S	4      #   \         d    \        P                  RT4        R# \         d     R# i ; i)	z�Return media paths already delivered in prior turns of this session
(MEDIA: tags / image_generate payloads), so an echoed old tag isn't re-sent.r#  NÚpeek_session_idz[Transcript read failed for session %s; media dedup runs with no history this turn (#100788)c              3   óf   <"  € T F&  pSV,          P                  R 4      R8X  g   K"  Vx € K(  	  R# 5i)ÚroleÚuserN©r¥   )rì   ÚiÚhistorys   & €r   rï   ÚGBasePlatformAdapter._history_media_paths_for_session.<locals>.<genexpr>7
  s*   øé € Ð\Ñ7�1¸7À1½:¿>¹>È&Ó;QÐU[Ñ;[�QŠQÓ7ùs   ƒ1§
1c              3   óT   "  € T F  qP                  R 4      R8X  g   K  Vx € K   	  R# 5i)r›  Ú	assistantNr�  )rì   r£  s   & r   rï   r   <
  s"   é € ÐbÑ.? sÇ7Á7È6Ã?ÐVaÑCaŸsšsÓ.?ùs   ‚(ž
()Ú_collect_history_media_pathsrˆ  )ro   r;  Úload_transcriptr‚  r   rX   r[   r$  r„  r  rÒ   rÌ  ÚremoveÚgateway.runr£  )
rë  rú  rä  ÚpeekÚ
session_idÚ
transcriptÚlast_user_idxÚ
last_replyr£  rŸ  s
   &&       @r   Ú _history_media_paths_for_sessionÚ4BasePlatformAdapter._history_media_paths_for_session
  s  ø€ ô ˜Ð.°Ó5ˆßÙð	ä˜5Ð"3°TÓ:ˆDÜ.6°t¯nªn™˜kÔ*À$ˆJØ×.Ñ.¨z×/HÐ/H¸[ÓIˆJ÷ Ùô �zÓ"ˆÜÜ\œœc '›l¨QÕ.°°BÔ7Ó\Ð^bódˆàÒ$Ø˜n˜}Ð-‰Gô Ñb¬h°wÔ.?ÓbÐdhÓiˆJØÒ%Ø—‘˜zÔ*ßÙÝ<Ù+¨GÓ4Ð4øô3 #ô 	Ü�N‰Nð6Ø7Bôò Üô 	Úð	ús#   š;C6 ÁC6 Ã6!D(ÄD(Ä#D(Ä'D(c                ó6   <€ V ^8„  d   QhRS[ RS[S[,          /# rù  r—  )r   rä  s   "€r   r   rà  D
  s"   ø€ ÷ ,ñ ,É#ð ,ÑRZÑ[^ÕR_ñ ,r   c              ƒ  óH  a aaaaa"  € RR/R V V3R lllp\         oSP                  RR7      '       g   V! R4       R# \        P                  ! 4       oSP	                  4       oRV3R lloVVVV V3R	 lp \
        P                  ! VR
RR7      P                  4         \        P                  ! S\        R7      G Rj  x€L
 #   \         d    SP                  4        T! RRR7        R# i ; i L0  \         d    T! R4        R# \         d    T! RRR7        R# i ; i5i)zCRun best-effort history lookup in a bounded isolated daemon thread.r   Fc                ó4   € V ^8„  d   QhR\         R\        RR/# )r   r*  r   r   Nr´   )r   s   "r   r   ÚRBasePlatformAdapter._bounded_history_media_paths_for_session.<locals>.__annotate__F
  s!   € ÷ 	;ñ 	;œsð 	;´ð 	;À$ñ 	;r   c                ój   <€ \         P                  R V ,           R,           SP                  SVR7       R# )z[%s] z= %s; delivering bare local file path(s) without history dedupr   N)r   rX   rF  )r*  r   rë  rú  s   &$€€r   Ú
_fail_openÚPBasePlatformAdapter._bounded_history_media_paths_for_session.<locals>._fail_openF
  s-   ø€ Ü�N‰NØ˜&Õ Ð#bÕbØ—	‘	˜;°ð ö ;r   )Úblockingz4Media-delivery history lookup capacity exhausted forNc                 ó„   <€ SP                  4       '       g)   Ve   SP                  V4      MSP                  V 4       R # R # r¼  )r  Úset_exceptionÚ
set_result)re   r   Úresult_futures   &&€r   Ú_publish_resultÚUBasePlatformAdapter._bounded_history_media_paths_for_session.<locals>._publish_resultQ
  s9   ø€ Ø ×%Ñ%×'Ò'Ø7<Ò7H�×,Ñ,¨UÔ3Ø#×.Ñ.¨vÓ6úñ (r   c                  óR  <€ R R r SP                  S4      p  \        P                  ! \        4      ;_uu_ 4        SP                  SW4       R R R 4       SP                  4        R #   \         d   pTp R p?LbR p?ii ; i  + '       g   i     L<; i  SP                  4        i ; ir¼  )r¬  r\  r\   r]   rÍ  Úcall_soon_threadsafeÚrelease)re   r   r   rº  Ú	admissionÚlooprë  rú  s      €€€€€r   Ú_workerÚMBasePlatformAdapter._bounded_history_media_paths_for_session.<locals>._workerV
  s‡   ø€ Ø  $�EðØ×>Ñ>¸{ÓK�ð$Ü×(Ò(¬×6Õ6Ø×-Ñ-¨o¸vÔM÷ 7ð ×!Ñ!Ö#øô !ô Ø•ûðú÷ 7×6ûð ×!Ñ!Õ#ús9   †A' ˜"B ºBÁB Á'A>Á2A9Á9A>ÂB	ÂB ÂB&zmedia-history-lookupT)ÚtargetrF  Údaemonz8Could not start media-delivery history lookup worker forr   ©r3   z,Timed out loading media-delivery history forz(Media-delivery history lookup failed for©NN)Ú_HISTORY_MEDIA_LOOKUP_ADMISSIONÚacquirer   Úget_running_loopÚcreate_futureÚ	threadingÚThreadr‹  r[   r¾  Úwait_forÚ%_HISTORY_MEDIA_LOOKUP_TIMEOUT_SECONDSÚTimeoutError)rë  rú  r³  rÁ  rº  r¿  rÀ  r¹  s   ff  @@@@r   Ú(_bounded_history_media_paths_for_sessionÚ<BasePlatformAdapter._bounded_history_media_paths_for_sessionD
  s	  ýé € ð	;¸÷ 	;ó 	;ô 4ˆ	Ø× Ñ ¨%Ð ×0Ò0ÙÐMÔNÙÜ×'Ò'Ó)ˆØ×*Ñ*Ó,ˆ÷	8÷

	$ñ 
	$ð	Ü×Ò GÐ2HÐQUÔV×\Ñ\Ô^ð	Ü ×)Ò)¨-ÔAfÔg×gÐgøô ô 	à×ÑÔÙÐQÐ\`ÕaÚð		úñ høÜô 	ÙÐEÔFÚÜô 	áÐAÈDÕQÚð	üsl   ˆA.D"Á7'C ÂC1 Â>C/Â?C1 ÃD"Ã%C,Ã(D"Ã+C,Ã,D"Ã/C1 Ã1DÄD"ÄDÄDÄD"ÄDÄD"Úis_reconnectc                ó&   <€ V ^8„  d   QhRS[ RS[ /# )r   rÒ  r   rO  )r   rä  s   "€r   r   rà  s
  s   ø€ ÷ Fñ F©Tð F¹dñ Fr   c             ƒ  ó   "  € R# 5i)uî   Connect and start receiving; True on success. ``is_reconnect``: the reconnect watcher is
re-establishing a dropped platform â€” adapters with a server-side update queue (Telegram)
must preserve it so outage-time messages aren't discarded.Nrt   )rë  rÒ  s   &$r   ÚconnectÚBasePlatformAdapter.connectr
  ó   é ‚ ùó   ‚c                ó   <€ V ^8„  d   QhRR/# r‘   rt   )r   rä  s   "€r   r   rà  y
  s   ø€ ÷ ,ñ , $ñ ,r   c              ƒ  ó   "  € R# 5i)zDisconnect from the platform.Nrt   r™  s   &r   Ú
disconnectÚBasePlatformAdapter.disconnectx
  r×  rØ  c                ón   <€ V ^8„  d   QhRS[ RS[ RS[S[ ,          RS[S[S[ S[3,          ,          RS[/# ©r   rC  r  Úreply_tor�   r   ©r8   rf  r|   rg  rI  )r   rä  s   "€r   r   rà  }
  sJ   ø€ ÷ `ñ `¡#ð `±ð `¹xÉ½}ð `Ù%¡d©3±¨8¥nÕ5ð`ÙAKñ`r   c              ƒ  ó   "  € R# 5i)zQSend ``content`` (may be markdown) to a chat; returns SendResult with message id.Nrt   ©rë  rC  r  rß  r�   s   &&&&&r   ÚsendÚBasePlatformAdapter.send|
  r×  rØ  c                ó<   <€ V ^8„  d   QhRS[ RS[ RS[S[ ,          /# )r   Úparent_chat_idrF  r   rI  )r   rä  s   "€r   r   rà  „
  s'   ø€ ÷ ñ ¹#ð ÁSð ÉXÑVYÍ]ñ r   c              ƒ  ó   "  € R# 5i)u¸   Create a fresh thread under ``parent_chat_id`` for a CLIâ†’platform session handoff; its id
as str, or None when unsupported/failed (the watcher then uses ``parent_chat_id``
directly).Nrt   )rë  ræ  rF  s   &&&r   Úcreate_handoff_threadÚ)BasePlatformAdapter.create_handoff_thread„
  s
   é € ñ ùrØ  Úfinalizec          
      ó8   <€ V ^8„  d   QhRS[ RS[ RS[ RS[RS[/# )r   rC  r‡   r  rê  r   ©r8   rµ   rI  )r   rä  s   "€r   r   rà  Š
  s<   ø€ ÷ @ñ @Ùð@Ù(+ð@Ù69ð@ÙHLð@ÙYcñ@r   c             ƒ  ó$   "  € \        RRR7      # 5i)a*  Edit a sent message (optional: success=False makes callers send anew). ``finalize`` marks
the last edit of a streamed response; surfaces with a distinct "in progress" state (DingTalk
AI Cards) close the message on it and set ``REQUIRES_EDIT_FINALIZE`` so it's routed even
when content is unchanged.FúNot supported©rK  r   ©rI  )rë  rC  r‡   r  rê  s   &&&&$r   Úedit_messageÚ BasePlatformAdapter.edit_messageŠ
  s   é € ô  %¨Ô?Ð?ùó   ‚c                ó,   <€ V ^8„  d   QhRS[ RS[ RS[/# )r   rC  r‡   r   r´   )r   rä  s   "€r   r   rà  ’
  s"   ø€ ÷ 	ñ 	©Cð 	¹Sð 	ÁTñ 	r   c              ƒ  ó   "  € R# 5i)a¨  Delete a sent message; True on success (platforms without a deletion API return False and
callers leave it). Used by the stream consumer's fresh-final cleanup to remove stale
previews.

Used by the stream consumer's fresh-final cleanup path (see openclaw/openclaw#72038) to remove
long-lived preview messages after sending the completed reply as a fresh message so the platform's
visible timestamp reflects completion time.
Frt   )rë  rC  r‡   s   &&&r   Údelete_messageÚ"BasePlatformAdapter.delete_message’
  s
   é € ñ ùrØ  c                ó    <€ V ^8„  d   QhRS[ /# rj   r–  )r   rä  s   "€r   r   rà  �
  s   ø€ ÷ Wñ W±3ñ Wr   c                ó   € \        R ^ 4      # )z†Default :class:`EphemeralReply` TTL from ``display.ephemeral_system_ttl``
(``0`` = no auto-delete); non-fatal if config is unreadable.c                  óJ   € \        \        R 4      P                  R^ 4      4      # )r  Úephemeral_system_ttl)r9   rM  r¥   rt   r   r   rš  ÚGBasePlatformAdapter._get_ephemeral_system_ttl_default.<locals>.<lambda>¡
  s   € ”Cœ¨	Ó2×6Ñ6Ð7MÈqÓQÔRr   r  r™  s   &r   Ú!_get_ephemeral_system_ttl_defaultÚ5BasePlatformAdapter._get_ephemeral_system_ttl_default�
  s   € ô ÙRÐTUóWð 	Wr   c                ó0   <€ V ^8„  d   QhRS[ RS[ RS[RR/# )r   rC  r‡   rŽ  r   Nr7   )r   rä  s   "€r   r   rà  £
  s+   ø€ ÷ ñ ±#ð Á3ð ÑUXð Ð]añ r   c                ó¦   a aaa€ R VVV V3R llpV! 4       p \         P                  ! V4       R#   \         d    TP                  4         R# i ; i)z¨Spawn a detached task that deletes ``message_id`` after ``ttl_seconds``; best-effort
(gateway restart, permission denied, Telegram 48h window) swallowed at debug level.c                ó   € V ^8„  d   QhRR/# r‘   rt   )r   s   "r   r   ÚDBasePlatformAdapter._schedule_ephemeral_delete.<locals>.__annotate__¦
  s   € ÷ 	nñ 	n 4ñ 	nr   c               “   ó*  <"  €  \         P                  ! \        ^\        S4      4      4      G Rj  x€L
  SP	                  SSR7      G Rj  x€L
  R#  L! L  \
         d/   p \        P                  RSP                  SST 4        Rp ? R# Rp ? ii ; i5i)é   N)rC  r‡   z*[%s] Ephemeral delete failed for %s/%s: %s)	r   r  r¯  r9   rö  r[   r   r«  rF  )r  rC  r‡   rë  rŽ  s    €€€€r   Ú_run_deleteÚCBasePlatformAdapter._schedule_ephemeral_delete.<locals>._run_delete¦
  s{   øé € ðnÜ—m’m¤C¨¬3¨{Ó+;Ó$<Ó=×=Ð=Ø×)Ñ)°'ÀjÐ)ÓQ×QÒQñ >ÙQøÜô nÜ—‘ÐIÈ4Ï9É9ÐV]Ð_iÐkl×mÒmûðnüsP   ƒB…,A ±A²A ÁAÁA ÁBÁA ÁA ÁBÁ"#BÂBÂBÂBN)r   rw  rÍ  rQ   )rë  rC  r‡   rŽ  r  Úcoros   ffff  r   Ú_schedule_ephemeral_deleteÚ.BasePlatformAdapter._schedule_ephemeral_delete£
  sC   û€ ÷	nó 	nñ ‹}ˆð	Ü×Ò Ö%øÜô 	à�J‰J�Lð	ús   ™1 ±AÁAz```
z
```
ú

i¸  c                ó    <€ V ^8„  d   QhRS[ /# rj   rk   )r   rä  s   "€r   r   rà  À
  s   ø€ ÷ 0ñ 0™Cñ 0r   c                ó   € R \        4        R2# )u   âš ï¸� r
  )rr  r™  s   &r   Ú
_EA_HEADERÚBasePlatformAdapter._EA_HEADER¿
  s   € àœÓ)Ð*¨$Ð/Ð/r   c                ó    <€ V ^8„  d   QhRS[ /# rj   rk   )r   rä  s   "€r   r   rà  Ä
  s   ø€ ÷ -ñ -¡#ñ -r   c                ó   € \        4        R 2# )z: )rs  r™  s   &r   Ú_EA_REASON_LABELÚ$BasePlatformAdapter._EA_REASON_LABELÃ
  s   € ä&Ó(Ð)¨Ð,Ð,r   c                ó    <€ V ^8„  d   QhRS[ /# rj   rk   )r   rä  s   "€r   r   rà  È
  s   ø€ ÷ 2ñ 2¡Sñ 2r   c                ó   € R \        4        2# )r
  )rt  r™  s   &r   Ú_EA_SMART_DENY_LINEÚ'BasePlatformAdapter._EA_SMART_DENY_LINEÇ
  s   € àÔ-Ó/Ð0Ð1Ð1r   c                ó2   <€ V ^8„  d   QhRS[ RS[RS[ RS[ /# )r   r   rÖ   r>   r   r7   )r   rä  s   "€r   r   rà  Ì
  s/   ø€ ÷ Fñ F¡ð F©Sð F¹#ð FÉ#ñ Fr   c                óh   € \        T ;'       g    R4      p \        V 4      V8”  d   V RV V,           # T # )zETruncate ``text`` to ``budget`` chars, appending ``suffix`` when cut.rn   N)r8   rÒ   )r   rÖ   r>   s   &&&r   Ú_truncate_previewÚ%BasePlatformAdapter._truncate_previewË
  s4   € ô �4—:�:˜2‹ˆÜ),¨T«°VÔ);ˆt�G�Vˆ}˜vÕ%ÐEÀÐEr   c                ó&   <€ V ^8„  d   QhRS[ RS[ /# rš  rk   )r   rä  s   "€r   r   rà  Ñ
  s   ø€ ÷ ñ ™sð ¡sñ r   c                ó   € V# )zPEscape hook for command preview/reason; HTML-mode platforms (Telegram) override.rt   )rë  r   s   &&r   Ú
_ea_escapeÚBasePlatformAdapter._ea_escapeÑ
  s   € àˆr   c                ó`   <€ V ^8„  d   QhRS[ RS[RS[ RS[S[S[ .S[ 3,          ,          RS[ /# )r   r   rÖ   r>   Úescaper   )r8   r9   rf  rh  )r   rä  s   "€r   r   rà  Õ
  sF   ø€ ÷ "ñ "™Cð "©ð "±cð "É8ÑT\Ñ^aÐ]bÑdgÐ]gÕThÕKið "Ñuxñ "r   c                óL  € \        T;'       g    R4      pT;'       g    V P                  pV P                  pV! V! V4      4      V8:  d   V# ^ \        V4      rvWg8  d<   Wg,           ^,           ^,          pV! V! VRV 4      4      V8:  d   TpK6  V^,
          pKA  VRV V,           # )uN  ``_truncate_preview`` measured after ``escape`` (default ``_ea_escape``) in
``message_len_fn`` units: the platform cap applies to the wire payload, and escaping
expands (``&`` â†’ ``&amp;``), so a raw-length cut can still overflow. Returns raw text (the
caller escapes); ``suffix`` rides outside ``budget`` like ``_truncate_preview``.rn   N)r8   r  r  rÒ   )	rë  r   rÖ   r>   r   rÙ   rÚ   rÛ   rÜ   s	   &&&&&    r   Ú_ea_fitÚBasePlatformAdapter._ea_fitÕ
  sœ   € ô
 �4—:�:˜2‹ˆØ×*Ð*˜4Ÿ?™?ˆØ×$Ñ$ˆÙ‘&˜“,Ó 6Ô)ØˆKØ”C˜“IˆBØŒgØ•7˜Q•; 1Õ$ˆCÙ‘f˜T $ 3˜ZÓ(Ó)¨VÔ3Ø’à˜1•W’Ø�C�Rˆy˜6Õ!Ð!r   c                ó,   <€ V ^8„  d   QhRS[ RS[RS[/# )r   rE  rF  r   )r8   rµ   r9   )r   rä  s   "€r   r   rà  è
  s#   ø€ ÷ #ñ #±Sð #Éð #ÑQTñ #r   c                ó   € V P                   # )zPChars of command preview that fit; platforms with a hard message cap compute it.)Ú_EA_CMD_BUDGET)rë  rE  rF  s   &&&r   Ú_exec_approval_cmd_budgetÚ-BasePlatformAdapter._exec_approval_cmd_budgetè
  s   € à×"Ñ"Ð"r   c                ó    <€ V ^8„  d   QhRS[ /# rj   rk   )r   rä  s   "€r   r   rà  ì
  s   ø€ ÷ uñ u¡3ñ ur   c                óh   € V P                   V P                  \        \        4       4      4      ,           # )zVThe "doing nothing means it will NOT run" line, with the configured approvals.timeout.)Ú_EA_DEADLINE_PREFIXr  ru  ro  r™  s   &r   Ú_ea_deadline_lineÚ%BasePlatformAdapter._ea_deadline_lineì
  s&   € à×'Ñ'¨$¯/©/Ô:WÔXpÓXrÓ:sÓ*tÕtÐtr   c                óB   <€ V ^8„  d   QhRS[ RS[S[ ,          RS[RS[ /# )r   rD  rE  rF  r   )r8   rf  rµ   )r   rä  s   "€r   r   rà  ð
  s7   ø€ ÷ Iñ IÙðIÙ)1±#­ðIÙMQðIÙ^añIr   c                ó  € Vf   \        4       pV P                  '       d0   T P                  \        T;'       g    R4      V P                  4      pT P                  \        T;'       g    R4      V P	                  W#4      4      pV P
                   V P                   V P                  V4       V P                   V P                   V P                  V4       V P                  4        2pV'       d   WPP                  ,           # T# )z÷Shared exec-approval prompt text: header + fenced (truncated) command + why it was
flagged + the deadline line, plus the smart-deny line. Buttons/trailing instructions stay
platform-local. ``description=None`` renders the localized default reason.rn   )rq  Ú_EA_REASON_BUDGETr"  r8   r'  r  Ú_EA_CODE_OPENr  Ú_EA_CODE_CLOSEr  r,  r  )rë  rD  rE  rF  Úcmd_previewr   s   &&&&  r   Ú_format_exec_approvalÚ)BasePlatformAdapter._format_exec_approvalð
  sâ   € ð
 ÒÜ0Ó2ˆKØ×!×!Ð!ØŸ,™,¤s¨;×+<Ð+<¸"Ó'=¸t×?UÑ?UÓVˆKØ—l‘lÜ�—�˜2Ó × >Ñ >¸{Ó Yó[ˆà—?‘?Ð#Ø×%Ñ%Ð& t§¡°{Ó'CÐ&DÀT×EXÑEXÐDYØ×(Ñ(Ð)¨$¯/©/¸+Ó*FÐ)GØ×)Ñ)Ó+Ð,ð.ˆ÷ 3?ˆt×.Ñ.Õ.ÐHÀDÐHr   ÚonceÚprimaryÚdenyÚdangerc                ó6   <€ V ^8„  d   QhRS[ S[S[3,          /# rj   rÁ  )r   rä  s   "€r   r   rà    s   ø€ ÷ "ñ "¡4©©S¨¥>ñ "r   c                ó   € \        4       # r¼  )rp  r™  s   &r   Ú_EA_ACTION_LABELSÚ%BasePlatformAdapter._EA_ACTION_LABELS  s   € äÓ!Ð!r   c                ó\   <€ V ^8„  d   QhRS[ RS[ RS[ RS[S[S[S[S[3,          ,          /# )r   Úallow_permanentÚallow_sessionrF  r   )rµ   r$  r%  r8   )r   rä  s   "€r   r   rà  	  sH   ø€ ÷ dñ dÙ&*ðdÙ;?ðdÙOSðdÙX\Ñ]bÑcfÑhkÑmpÐcpÕ]qÕXrñdr   c          	     ó$  € R.pV'       g3   V'       d+   VP                  R4       V'       d   VP                  R4       VP                  R4       V Uu. uF1  qPP                  V,          WPP                  P                  VR4      3NK3  	  up# u upi )zê``(label, choice, style)`` rows for the approval buttons. A smart deny is an owner
override for one operation only, so it offers neither the session nor the permanent tier;
the permanent tier is never offered without the session tier.r6  ÚsessionÚalwaysr8  rn   )r­  r<  Ú_EA_ACTION_STYLESr¥   )rë  r?  r@  rF  r@  r>  s   &$$$  r   Ú_exec_approval_actionsÚ*BasePlatformAdapter._exec_approval_actions	  ss   € ð
 �(ˆß§Ø�N‰N˜9Ô%ßØ—‘˜xÔ(Ø�‰�vÔÙ[bÓcÑ[bÐVW×'Ñ'¨Õ*¨A×/EÑ/E×/IÑ/IÈ!ÈRÓ/PÓQÑ[bÑcÐcùÒcs   Á7Bc                ó    <€ V ^8„  d   QhRS[ /# rj   rO  )r   rä  s   "€r   r   rà    s   ø€ ÷ dñ d©tñ dr   c                ó:   € V P                   \        P                   J# )z‘True when the adapter renders native approval buttons (overrides the prompt hook);
the runner otherwise sends the plain-text ``/approve`` prompt.)Ú_send_exec_approval_promptr¦  )r“  s   &r   Úsupports_exec_approval_buttonsÚ2BasePlatformAdapter.supports_exec_approval_buttons  s   € ð ×-Ñ-Ô5H×5cÑ5cÐcÐcr   c                ó†   <€ V ^8„  d   QhRS[ RS[ RS[ RS[S[ ,          RS[S[S[ S[3,          ,          RS[RS[RS[R	S[/	# )
r   rC  rD  rú  rE  r�   r?  r@  rF  r   )r8   rf  r|   rg  rµ   rI  )r   rä  s   "€r   r   rà    sk   ø€ ÷ =ñ =Ùð=Ù%(ð=Ù7:ð=ÙIQÑRUÍð=á™4¡¡S �>Õ*ð=áDHð=á`dð=ñ ð=ñ 
ñ	=r   c	              ƒ  óæ   "  € Vf   \        4       p\        YT\        T;'       g    R4      WHV P                  W$V4      V P	                  WgVR7      R7      p	V P                  V	4      G Rj  x€L
 #  L5i)zÄInteractive exec-approval prompt; a press resolves via
``tools.approval.resolve_gateway_approval``. Text and choice set are shared; adapters
render them natively in ``_send_exec_approval_prompt``.Nrn   )r?  r@  rF  )rC  rú  r�   rD  rE  rF  r   r>  )rq  r:  r8   r4  rE  rI  )
rë  rC  rD  rú  rE  r�   r?  r@  rF  rÅ  s
   &&&&&&&&& r   Úsend_exec_approvalÚ&BasePlatformAdapter.send_exec_approval  s}   é € ð ÒÜ0Ó2ˆKÜ#Ø¸xÔQTÐU\×UbÐUbÐ`bÓQcØ#Ø×+Ñ+¨GÀ,ÓOØ×/Ñ/Ø /Ð[gð 0ó iô	jˆð ×4Ñ4°VÓ<×<Ð<Ñ<ùs   ‚A(A1Á*A/Á+A1c                ó&   <€ V ^8„  d   QhRS[ RS[/# )r   rÅ  r   )r:  rI  )r   rä  s   "€r   r   rà  .  s    ø€ ÷ @ñ @Ñ7Ið @Éjñ @r   c              ƒ  ó$   "  € \        RRR7      # 5i)zKRender ``prompt`` with the platform's native buttons; the default has none.Frî  rï  rð  )rë  rÅ  s   &&r   rI  Ú.BasePlatformAdapter._send_exec_approval_prompt.  s   é € ä %¨Ô?Ð?ùró  c                ó^   <€ V ^8„  d   QhRS[ RS[RS[RS[S[ S[S[S[3,          3,          /# )r   ÚoptionsÚpageÚper_pager   )r$  r9   r%  r|   r8   rg  )r   rä  s   "€r   r   rà  3  s@   ø€ ÷ (ñ (¡Tð (±ð (Áð (ÉÉdÑTXÑY\Ñ^aÐYaÕTbÐNbÕHcñ (r   c                ó4  € \        V 4      p\        ^W2,           ^,
          V,          4      p\        ^ \        W^,
          4      4      pW,          \        W,          V,           V4      reV^8”  d   \        RV^,           WcR7      MRpRVRVRVRVRVR	V/pWV V3# )
uÈ   Shared picker pagination: clamp ``page``, slice ``options`` -> ``(page_options, meta)``
with ``page``/``total_pages``/``start``/``end``/``total``/``page_info`` (`` (Nâ€“M of T)``,
empty for one page).zgateway.picker.page_info)r‹  rŠ  r±  rn   rU  Útotal_pagesr‹  rŠ  r±  Ú	page_info)rÒ   r¯  Úminr   )	rT  rU  rV  r±  rX  r‹  rŠ  rY  Úmetas	   &&&      r   Ú_format_choice_pageÚ'BasePlatformAdapter._format_choice_page2  s£   € ô
 �G“ˆÜ˜!˜eÕ.°Õ2°xÕ?Ó@ˆÜ�1”c˜$¨a¥Ó0Ó1ˆØ•_¤c¨$­/¸HÕ*DÀeÓ&LˆsØ\gÐjkÔ\k”AÐ0¸À½	ÀsÕXÐqsˆ	Ø &¨¨m¸[È'ÐSXØ˜#˜w¨¨{¸Ið Gˆà˜SÐ! 4Ð'Ð'r   c                ój   <€ V ^8„  d   QhRS[ RS[ RS[ RS[ RS[ RS[S[S[ S[3,          ,          RS[/# )r   rC  rí  r�  rú  Ú
confirm_idr�   r   rà  )r   rä  s   "€r   r   rà  @  s[   ø€ ÷ @ñ @Ùð@Ù#&ð@Ù14ð@ÙCFð@ÙTWð@á™4¡¡S �>Õ*ð@á6@ñ@r   c              ƒ  ó$   "  € \        RRR7      # 5i)aM  Three-option slash-command confirmation (e.g. ``/reload-mcp``). Button adapters render
Approve Once / Always Approve / Cancel and MUST resolve via
``GatewayRunner._resolve_slash_confirm(confirm_id, "once"|"always"|"cancel")``. Default (not
supported) falls through to the gateway text fallback
(``/approve``/``/always``/``/cancel``).Frî  rï  rð  )rë  rC  rí  r�  rú  r_  r�   s   &&&&&&&r   Úsend_slash_confirmÚ&BasePlatformAdapter.send_slash_confirm@  s   é € ô  %¨Ô?Ð?ùró  c                óz   <€ V ^8„  d   QhRS[ RS[ RS[S[,          RS[ RS[ RS[S[S[ S[3,          ,          RS[/# )r   rC  Úquestionr@  Ú
clarify_idrú  r�   r   )r8   rf  r$  r|   rg  rI  )r   rä  s   "€r   r   rà  J  s_   ø€ ÷ Qñ QÙðQÙ&)ðQÙ4<¹TµNðQÙPSðQáðQá$,©T±#±s°(­^Õ$<ðQáHRñQr   c           
   ƒ  óÞ  "  € V'       d     ^ RI Hp \        \        V! V4      RR4      4      pV'       d   \        R4      M
\        R4      p	\        V^R7       U
Uu. uF  w  r«\        RW«R7      NK  	  pp
pR	P                  \        R
VR7      R.VORNV	N4      p^ RI Hp V! V4       M\        R
VR7      pV P                  WVR7      G Rj  x€L
 #   \         d    Rp L³i ; iu upp
i  L5i)av  Clarify prompt; button-capable adapters SHOULD override. Multiple choice (``choices``):
one button per choice plus "Other"; callbacks MUST resolve via
``tools.clarify_gateway.resolve_gateway_clarify(clarify_id, response)``, "Other" calls
``mark_awaiting_text(clarify_id)``. Open-ended: send the question as text (the gateway
text-intercept resolves the next message). Default: numbered list +
``mark_awaiting_text``. Adapters whose prompt is a persistent card MAY define
``async retire_clarify_card(clarify_id, notice)``; the gateway calls it when the clarify
ends without a click (timeout, session reset, superseding free prose).)Úget_pendingÚmulti_selectFzgateway.clarify.hint_multizgateway.clarify.hint_singlerº  zgateway.clarify.option_line)Úindexr?  r†  zgateway.clarify.question)rd  rn   )Úmark_awaiting_text©rC  r  r�   N)
Útools.clarify_gatewayrg  rµ   ro   r[   r   Ú	enumeraterÆ   rj  rã  )rë  rC  rd  r@  re  rú  r�   rg  Ú	_is_multiÚhintrž  r?  Únumberedr   rj  s   &&&&&&&        r   Úsend_clarifyÚ BasePlatformAdapter.send_clarifyJ  só   é € ÷ ð"Ý=Ü ¤©°ZÓ)@À.ÐRWÓ!XÓY�	÷ 7@”1Ð1Ô2ÄQÐGdÓEeˆDä)2°7À!Õ)DôFÙ)D™I˜Aô Ð7¸q×PÙ)Dð ñ Fà—9‘9œaÐ :ÀXÔNÐPRÐhÐU]ÐhÐ_aÐhÐcgÐhÓiˆDå@Ù˜zÕ*äÐ/¸(ÔCˆDØ—Y‘Y wÀx�YÓP×PÐPøô ô "Ø!’	ð"üóFñ QùsE   ‚	C-Œ"C ®C-¶&C-ÁC%Á4AC-ÃC+ÃC-ÃC"ÃC-Ã!C"Ã"
C-c                ó„   <€ V ^8„  d   QhRS[ RS[S[ ,          RS[ RS[S[ ,          RS[S[S[ S[3,          ,          RS[/# )r   rC  r  r  rß  r�   r   rà  )r   rä  s   "€r   r   rà  g  s[   ø€ ÷ gñ gÙðgÙ%-©c¥]ðgÙ=@ðgÙLTÑUXÍMðgá™4¡¡S �>Õ*ðgá6@ñgr   c              ƒ  óD   "  € V P                  WWER7      G Rj  x€L
 #  L5i)zPSend a notice privately when the platform supports it; default is a normal send.©rC  r  rß  r�   N©rã  )rë  rC  r  r  rß  r�   s   &&&&&&r   Úsend_private_noticeÚ'BasePlatformAdapter.send_private_noticeg  s    é € ð —Y‘Y wÈ(�YÓf×fÐfÑfùs   ‚ ™š c                ó$   <€ V ^8„  d   QhRS[ RR/# ©r   rC  r   Nrk   )r   rä  s   "€r   r   rà  m  s   ø€ ÷ `ñ `©ð `Àñ `r   c              ƒ  ó   "  € R# 5i)zQSend a typing indicator; ``metadata`` carries platform context (Slack thread_id).Nrt   ©rë  rC  r�   s   &&&r   Úsend_typingÚBasePlatformAdapter.send_typingm  r×  rØ  c                ó$   <€ V ^8„  d   QhRS[ RR/# rz  rk   )r   rä  s   "€r   r   rà  p  s   ø€ ÷ Xñ X©ð X°ñ Xr   c              ƒ  ó   "  € R# 5i)zIStop a persistent typing indicator; override where typing runs as a loop.Nrt   r  s   &&r   Ústop_typingÚBasePlatformAdapter.stop_typingp  r×  rØ  c          
      ó8   <€ V ^8„  d   QhRS[ RS[RS[RS[RS[/# )r   r   rF  Úvar_kwrƒ  r   )rh  r8   rµ   )r   rä  s   "€r   r   rà  t  s8   ø€ ÷ Oñ O™8ð O©3ð O¹4ð OÉ$ð OÑSWñ Or   c               óB  €  \         P                  ! V 4      P                  pY9   ;'       g[    T;'       dQ    \
        ;QJ d*    R TP                  4        4       F  '       g   K   R# 	  R# ! R TP                  4        4       4      #   \        \        3 d    Tu # i ; i)z‘Whether ``fn``'s signature takes keyword ``name`` (``var_kw``: a ``**kwargs`` also
counts); ``unknown`` when the signature can't be introspected.c              3   ól   "  € T F*  qP                   \        P                  P                  J x € K,  	  R # 5ir¼  )r«   ÚinspectÚ	ParameterÚVAR_KEYWORDrq  s   & r   rï   Ú5BasePlatformAdapter._accepts_kwarg.<locals>.<genexpr>{  s'   é € ð 1NÙ=L¸�F‰F”g×'Ñ'×3Ñ3Õ3»_ùs   ‚24TF)r‡  Ú	signatureÚ
parametersrž  rñ   rö   Úvalues)r   rF  r„  rƒ  Úparamss   &&$$ r   Ú_accepts_kwargÚ"BasePlatformAdapter._accepts_kwargs  s§   € ð	Ü×&Ò& rÓ*×5Ñ5ˆFð ‰~÷ Oð O &÷ #Nð #N¯S«Sñ 1NØ=C¿]¹]¼_ó1N¯S¬Sð 	OªSð 	O¨Sñ 1NØ=C¿]¹]¼_ó1Nó .Nð 	Oøô œ:Ð&ô 	ØŠNð	ús   ‚ B ÂBÂBc                ó$   <€ V ^8„  d   QhRS[ RR/# rz  rk   )r   rä  s   "€r   r   rà  ~  s   ø€ ÷ (ñ (¹ð (Ètñ (r   c              ƒ  óÚ   "  € V'       dB   V P                  V P                  RRRR7      '       d   V P                  WR7      G Rj  x€L
  R# V P                  V4      G Rj  x€L
  R#  L! L5i)záStop typing, forwarding ``metadata`` only if ``stop_typing`` accepts it (Slack AI
status is per thread, so dropping metadata could clear a sibling thread; introspecting
keeps legacy ``stop_typing(chat_id)`` adapters working).r�   TF©r„  rƒ  rÃ  N)r�  r�  r|  s   &&&r   Ú_stop_typing_with_metadataÚ.BasePlatformAdapter._stop_typing_with_metadata~  sh   é € ÷ ˜×+Ñ+Ø× Ñ  *°TÀ5ð ,÷ Jò Jà×"Ñ" 7Ð"Ó>×>Ð>ÙØ×Ñ˜wÓ'×'Ò'ñ ?á'ùs(   ‚-A+°A+ÁA'ÁA+Á A)Á!A+Á)A+c          
      ó„   <€ V ^8„  d   QhRS[ RS[S[S[ S[ 3,          ,          RS[S[S[ S[3,          ,          RS[RS[/# )r   rC  rT  r�   Úhuman_delayr   )r8   r$  r%  rf  r|   rg  r¨  rI  )r   rä  s   "€r   r   rà  ˆ  sV   ø€ ÷ "Fñ "FÙð"FÙ$(©©s±C¨x­Õ$9ð"Fá™4¡¡S �>Õ*ð"Fá@Eð"FáPZñ"Fr   c           	   ƒ  óz  "  € RpV EF<  w  rgV^ 8”  d   \         P                  ! V4      G Rj  x€L
   \        P                  RV P                  \        V4      V'       d
   VR,          MR4       VP                  R4      '       d$   ^ RIHp V P                  RV! VR	,          4      /r©M6V P                  V4      '       d   V P                  R
V/r©MV P                  RV/r©T	! RRV/V
BRT;'       g    RRV/B G Rj  x€L
 pVP                  '       g/   \        P                  RV P                  VP                  4       EK:  RpEK?  	  V'       g   \!        RRR7      # \!        TV'       d   RR7      # RR7      #  ELL L  \         d0   p\        P                  RT P                  TRR7        Rp?EK¬  Rp?ii ; i5i)uŽ  Send ``(url, alt)`` images (``http(s)://`` or ``file://``) one by one (GIFs via
``send_animation``, local files via ``send_image_file``); override to bundle natively
(Signal). Returns success when at least one image was delivered â€” the outcome
the turn-level delivery tracker records; every override must return the same
aggregate, or a media-only turn on that platform reports FAILURE (#106153).FNz[%s] Sending image: %s (alt=%s):Né   Nrn   úfile://)Úurl2pathnameÚ
image_path:é   NNÚanimation_urlÚ	image_urlrC  Úcaptionr�   z[%s] Failed to send image: %sTz[%s] Error sending image: %sr   zno images to sendrï  zall images failed to sendrt   )r   r  r   rÊ  rF  r   r=  Úurllib.requestr›  Úsend_image_fileÚ_is_animation_urlÚsend_animationÚ
send_imagerK  r   r[   rI  )rë  rC  rT  r�   r—  Ú	deliveredrŸ  Úalt_textr›  ÚsenderÚurl_kwÚ
img_resultÚimg_errs   &&&&&        r   Úsend_multiple_imagesÚ(BasePlatformAdapter.send_multiple_imagesˆ  s£  é € ð ˆ	Ü#)ÑˆIØ˜QŒÜ—m’m KÓ0×0Ð0ð`Ü—‘Ð=¸t¿y¹yÜ,¨YÓ7Ï(¸À#¾ÐXZô\à×'Ñ'¨	×2Ò2Ý;Ø%)×%9Ñ%9¸LÉ,ÐW`ÐacÕWdÓJeÐ;f™FØ×+Ñ+¨I×6Ò6Ø%)×%8Ñ%8¸?ÈIÐ:V™Fà%)§_¡_°{ÀIÐ6N˜FÙ#)ñ $\Ø#ð$\Ø'-ñ$\Ø7?×7GÐ7GÀ4ð$\ØRZò$\÷ \�
à!×)×)Ð)Ü—L‘LÐ!@À$Ç)Á)ÈZ×M]ÑM]×^à $“Iñ% $*÷* Ü eÐ3FÔGÐGÜØß#�$ôFð 	Fà)DôFð 	Fò+ 1ñ\øô ô `Ü—‘Ð;¸T¿Y¹YÈÐZ^�×_Ó_ûð`üsu   ‚+F;­E9®F;³AE>Â9E>Ã 0E>Ã1E>Ã<E<Ã=E>Ä+E>Ä>F;ÅE>ÅF;Å*F;Å<E>Å>F8Æ	#F3Æ,F;Æ3F8Æ8F;c                ó„   <€ V ^8„  d   QhRS[ RS[ RS[S[ ,          RS[S[ ,          RS[S[S[ S[3,          ,          RS[/# )r   rC  rŸ  r   rß  r�   r   rà  )r   rä  s   "€r   r   rà  ¬  sZ   ø€ ÷ dñ dÙðdÙ'*ðdÙ5=¹cµ]ðdá™3•-ðdá2:¹4ÁÁSÀ½>Õ2JðdáV`ñdr   c              ƒ  óf   "  € V'       d   V RV 2MTpV P                  WWER7      G Rj  x€L
 #  L5i)zFSend an image natively; default falls back to sending the URL as text.r†  ru  Nrv  )rë  rC  rŸ  r   rß  r�   r   s   &&&&&& r   r¥  ÚBasePlatformAdapter.send_image¬  s4   é € ÷ -4�'�˜"˜Y˜KÑ(¸ˆØ—Y‘Y wÀx�YÓc×cÐcÑcùs   ‚(1ª/«1c                ó„   <€ V ^8„  d   QhRS[ RS[ RS[S[ ,          RS[S[ ,          RS[S[S[ S[3,          ,          RS[/# )r   rC  rž  r   rß  r�   r   rà  )r   rä  s   "€r   r   rà  ³  sZ   ø€ ÷ mñ mÙðmÙ+.ðmÙ9AÁ#½ðmá™3•-ðmá2:¹4ÁÁSÀ½>Õ2JðmáV`ñmr   c              ƒ  óF   "  € V P                  WW4VR7      G Rj  x€L
 #  L5i)zWSend a GIF as a native animation (auto-plays inline); default falls back to
send_image.)rC  rŸ  r   rß  r�   N)r¥  )rë  rC  rž  r   rß  r�   s   &&&&&&r   r¤  Ú"BasePlatformAdapter.send_animation³  s3   é € ð
 —_‘_Ø¸gÐckð %ó m÷ mð 	mñ mùs   ‚!š›!c                ó&   <€ V ^8„  d   QhRS[ RS[/# )r   r  r   r´   )r   rä  s   "€r   r   rà  ¼  s   ø€ ÷ :ñ :™sð :¡tñ :r   c                ól   € V P                  4       P                  R4      ^ ,          P                  R4      # )z=Check if a URL points to an animated GIF (vs a static image).rU  r0   )rp   r›  Úendswith)r  s   &r   r£  Ú%BasePlatformAdapter._is_animation_url»  s+   € ð �y‰y‹{× Ñ  Ó% aÕ(×1Ñ1°&Ó9Ð9r   c                ób   <€ V ^8„  d   QhRS[ RS[S[S[S[ S[ 3,          ,          S[ 3,          /# r¿  ©r8   r%  r$  )r   rä  s   "€r   r   rà  Á  s6   ø€ ÷ Bñ B¡ð B©©d±5¹¹c¸µ?Õ.CÁSÐ.HÕ(Iñ Br   c                ót  aa€ RpRpR
p\         P                  ! W4       Uau. uFg  o\        ;QJ d    V3R lV 4       F  '       g   K   RM	  RM! V3R lV 4       4      '       g   KE  SP                  ^4      SP                  ^4      3NKi  	  ppVP	                  R \         P                  ! W 4       4       4       V'       g   WP3# V UUu0 uF  w  rgVkK	  	  uppoV3R lpT p	W3 F  p
\         P
                  ! W¨V	4      p	K  	  V\         P
                  ! RR	V	4      P                  4       3# u upi u uppi )z�Extract ``![alt](url)`` and ``<img src=...>`` image URLs from a response;
returns ``([(url, alt_text), ...], content with those tags removed)``.z$!\[([^\]]*)\]\((https?://[^\s\)]+)\)zA<img\s+src=["\']?(https?://[^\s"\'<>]+)["\']?\s*/?>\s*(?:</img>)?c              3   óÔ   <"  € T F]  pSP                  ^4      P                  4       P                  V4      ;'       g#    VSP                  ^4      P                  4       9   x € K_  	  R# 5i)r   N)r‰  rp   r¶  )rì   r²   r&  s   & €r   rï   Ú5BasePlatformAdapter.extract_images.<locals>.<genexpr>Ë  sU   øé € ð -Ù$+˜Sð Ÿ™ ›×)Ñ)Ó+×4Ñ4°SÓ9×VÐV¸SÀAÇGÁGÈAÃJ×DTÑDTÓDVÑ=VÔVÛ$+ùs
   ƒ9A(½+A(TFc              3   óF   "  € T F  qP                  ^4      R3x € K  	  R# 5i)r  rn   N)r‰  )rì   rí  s   & r   rï   r¼  Í  s   é € Ð[Ñ8Z¨u—{‘{ 1“~ rÕ*Ó8Zùs   ‚!c                 óž   <€ V P                   ^8¼  d   V P                  ^4      MV P                  ^4      pVS9   d   R# V P                  ^ 4      # )r   rn   )Ú	lastindexr‰  )rí  r  Úextracted_urlss   & €r   Ú_remove_if_extractedÚ@BasePlatformAdapter.extract_images.<locals>._remove_if_extractedÓ  s?   ø€ Ø$)§O¡O°qÔ$8�%—+‘+˜a”.¸e¿k¹kÈ!»nˆCØ Ô.�2ÐB°E·K±KÀ³NÐBr   ú\n{3,}r
  )r.   r,   r-   r0   r/   z	fal.mediazfal-cdnzreplicate.delivery)r�  rµ  rö   r‰  r“  r¼  r‹   )r  Ú
md_patternÚhtml_patternÚmarkersr&  rT  r  rí   rÁ  rÑ  r3  rÀ  s   &   `      @r   Úextract_imagesÚ"BasePlatformAdapter.extract_imagesÀ  s  ù€ ð =ˆ
à[ˆð)ˆä46·K²KÀ
Ô4Tô .Ñ4T¨qß“Sô -Ù$+ó-—S—S’Sô -Ù$+ó-÷ -ô +�1—7‘7˜1“:˜qŸw™w q›zÓ*Ñ4Tˆð .ð 	�‰Ñ[¼¿ºÀLÔ8ZÓ[Ô[ßØ�?Ð"á,2Ô3©F¡& #›#©FÒ3ˆõ	Cð ˆØ"Ó1ˆGÜ—f’f˜W¸GÓDŠGñ 2à”r—v’v˜i¨°Ó9×?Ñ?ÓAÐAÐAùò.ùó 4s   ¢D/²D/Á	D/Á)&D/ÃD4c                ó„   <€ V ^8„  d   QhRS[ RS[ RS[S[ ,          RS[S[ ,          RS[S[S[ S[3,          ,          RS[/# )r   rC  rÍ   r   rß  r�   r   rà  )r   rä  s   "€r   r   rà  Û  sZ   ø€ ÷ Uñ UÙðUÙ(+ðUÙ6>¹sµmðUá™3•-ðUá2:¹4ÁÁSÀ½>Õ2JðUá`jñUr   c           	   ‹  óH   "  € V P                  RRW!W4V4      G Rj  x€L
 #  L5i)znSend audio as a native voice message (Telegram bubble / Discord attachment).
Default: friendly failure notice.Ú
send_voicer§   N©Ú_send_media_fallback_notice)rë  rC  rÍ   r   rß  r�   rª  s   &&&&&&,r   rË  ÚBasePlatformAdapter.send_voiceÛ  s3   é € ð
 ×5Ñ5Ø˜' :¸È8óU÷ Uð 	Uñ Uùr(  r¬   c                ó¦   <€ V ^8„  d   QhRS[ RS[ RS[ RS[ RS[S[ ,          RS[S[ ,          RS[S[S[ S[3,          ,          RS[S[ ,          R	S[/	# )
r   Úmethodr«   r6   rC  r   rß  r�   r¬   r   rà  )r   rä  s   "€r   r   rà  ã  s~   ø€ ÷ 
Fñ 
FÙð
FÙ!$ð
FÙ,/ð
FÙ:=ð
FÙHPÑQTÍð
Fá™3•-ð
Fá+3±D¹¹c¸µNÕ+Cð
FáS[Ñ\_ÕS`ð
Fñ 
ñ
Fr   c          	   ƒ  ó¢   "  € \         P                  RV P                  WV4       \        W(4      p	V P	                  WIWVVVR7      G Rj  x€L
 #  L5i)z¹Shared default for send_voice/send_video/send_document/send_image_file. The local path is
logged but NEVER echoed into chat (host layout leak); only the caller's ``file_name`` is
shown.z3[%s] %s fallback: native %s send unavailable for %s)r   rß  r�   Úshown_metadataN)r   rX   rF  r°   Úemit_media_warning)
rë  rÐ  r«   r6   rC  r   rß  r�   r¬   r   s
   &&&&&&&&$ r   rÍ  Ú/BasePlatformAdapter._send_media_fallback_noticeã  sZ   é € ô 	�‰ÐLÈdÏiÉiÐY_ÐgkÔlÜ" 4Ó3ˆØ×,Ñ,¨WÀGÐiqØ<Dð -ó F÷ Fð 	Fñ Fùs   ‚AAÁAÁ	Arß  r�   Úlogical_platformc                ó<   <€ V ^8„  d   QhRS[ RS[ RS[S[,          /# )r   rC  r  r   )r8   rf  rI  )r   rä  s   "€r   r   rà  ï  s/   ø€ ÷ Wñ WÙðWÙ%(ðWá	‘*Õ	ñWr   c             ƒ  óz   "  € V P                  WQVR7      '       g   R# V P                  WW4R7      G Rj  x€L
 #  L5i)a*  Present a classified channel diagnostic in the caller's owning scope.

None means suppressed, NOT successfully sent. Transport receipts/exceptions
pass through unchanged; logs and producer state belong outside this boundary.
Existing routing/stream metadata is preserved, never inferred from text.
©rC  r�   N©rß  r�   )Úwarning_notifications_enabledrã  )rë  rC  r  rß  r�   rÕ  s   &&&$$$r   Úemit_warningÚ BasePlatformAdapter.emit_warningï  s;   é € ð ×1Ñ1Ð2BÐ^fÐ1×gÒgÙØ—Y‘Y˜w¸(�YÓV×VÐVÑVùs   ‚2;´9µ;r   rÒ  c                ó,   <€ V ^8„  d   QhRS[ RS[ RS[/# )r   rC  Únoticer   ©r8   rI  )r   rä  s   "€r   r   rà  ü  s'   ø€ ÷ 7ñ 7Ùð7Ù$'ð7ñ 
ñ7r   c             ƒ  óÒ   "  € T P                  Y'       d   V RV 2MTWFR7      G Rj  x€L
 pVe   V# V'       d   V P                  WWER7      G Rj  x€L
  \        RVR7      #  L: L5i)ab  Present an optional media diagnostic without losing the requested caption.

Preserve the legacy fallback-text receipt when shown (``shown_metadata`` is the exact
metadata the legacy shown path passed; default None keeps callers that sent none
byte-identical). When hidden, preserve the media failure even if the independent
caption itself was delivered.
r†  rÙ  NFrï  )rÛ  rã  rI  )rë  rC  rÞ  r   rß  r�   rÒ  re   s   &&&$$$$ r   rÓ  Ú&BasePlatformAdapter.emit_media_warningü  sw   é € ð ×(Ñ(¨ÎG°W°I¸RÀ¸xÑ2HÐY_Ø2:ð )ó U÷ UˆàÒØˆMßØ—)‘)˜G°x�)ÓS×SÐSÜ %¨vÔ6Ð6ñUñ
 Tùs&   ‚&A'¨A#©A'»A'ÁA%ÁA'Á%A'rC  c                óL   <€ V ^8„  d   QhRS[ RS[S[ ,          RS[S[ ,          /# )r   ÚvisibleÚhiddenr   rI  )r   rä  s   "€r   r   rà    s9   ø€ ÷ ñ ¡Cð ±¹#µð ñ  @Hñ  ILõ  @Mñ r   c               ó<   € V P                  W4VR7      '       d   V# V# )züProject mixed content: the diagnostic variant when visible, else the requested remainder.

For payloads that combine a requested result (caption, answer) with an automatic
diagnostic. The requested part must be present in BOTH variants; never hide it.
rØ  ©rÚ  )rë  rã  rä  rÕ  rC  r�   s   &&&$$$r   Úwarning_textÚ BasePlatformAdapter.warning_text  s&   € ð ×-Ñ-Ð.>ÐZbÐ-×cÒcØˆNØˆr   c                ó    <€ V ^8„  d   QhRS[ /# rj   rO  )r   rä  s   "€r   r   rà    s   ø€ ÷ Pñ PÑfjñ Pr   c               óF   € ^ RI Hp T! T;'       g    V P                  4      # )zNPresentation policy under the caller's owning profile; old plugins inherit it.ræ  )Úgateway.warning_notificationsrÚ  rq   )rë  rÕ  rC  r�   rÚ  s   &&$$ r   rÚ  Ú1BasePlatformAdapter.warning_notifications_enabled  s   € åOÙ,Ð-=×-NÐ-NÀÇÁÓOÐOr   c                ó&   <€ V ^8„  d   QhRS[ RS[ /# rš  rk   )r   rä  s   "€r   r   rà    s   ø€ ÷ 
=ñ 
=¡Sð 
=©Sñ 
=r   c                óâ   €  ^ RI Hp V! VRR7      #   \         dR    \        P                  ! RRT\        P
                  R7      p\        P                  ! RRT4      P                  4       u # i ; i)	z«Chat Markdown -> transcript-like spoken script (reasoning blocks removed,
headings/bullets flattened, units expanded). Chunking and delivery limits are the TTS tool's
job.)Úprepare_spoken_textN)Ú	max_charsz<think[\s>].*?</think>rÈ  )r¨  z[*_`#\[\]()]rn   )Útools.tts_text_normalizerï  r[   r�  r¼  ÚDOTALLr‹   )rë  r   rï  s   && r   Úprepare_tts_textÚ$BasePlatformAdapter.prepare_tts_text  s[   € ð	=ÝDÙ& t°tÔ<Ð<øÜô 	=ä—6’6Ð3°S¸$ÄbÇiÁiÔPˆDÜ—6’6˜/¨2¨tÓ4×:Ñ:Ó<Ò<ð	=ús   ‚ ’AA.Á-A.c                ó,   <€ V ^8„  d   QhRS[ RS[ RS[/# )r   rC  rÍ   r   rß  )r   rä  s   "€r   r   rà  *  s'   ø€ ÷ Wñ W¡cð W±sð WÉñ Wr   c              ‹  óJ   "  € V P                   ! RRVRV/VB G Rj  x€L
 #  L5i)zSPlay auto-TTS audio; override for invisible playback (Web UI). Default: send_voice.rC  rÍ   Nrt   )rË  )rë  rC  rÍ   rª  s   &&&,r   Úplay_ttsÚBasePlatformAdapter.play_tts*  s'   é € à—_’_ÑV¨WÐVÀÐVÈvÑV×VÐVÑVùó   ‚#œ!�#c                ó,   <€ V ^8„  d   QhRS[ RS[RS[/# )r   rC  Úaudio_formatr   )r8   rv  rµ   )r   rä  s   "€r   r   rà  6  s#   ø€ ÷ ñ ©cð Áð ÑQUñ r   c                ó   € R# )zEReturn True when this adapter can accept streaming PCM for *chat_id*.Frt   )rë  rC  rû  s   &&&r   Úsupports_streaming_ttsÚ*BasePlatformAdapter.supports_streaming_tts6  s   € ár   c          	      óh   <€ V ^8„  d   QhRS[ RS[RS[S[S[ S[3,          ,          RS[S[,          /# )r   rC  rû  r�   r   )r8   rv  rf  r|   rg  rw  )r   rä  s   "€r   r   rà  :  sA   ø€ ÷ ñ ÙðÙ*5ðÙAIÉ$ÉsÑTWÈxÍ.ÕAYðá	Ñ$Õ	%ñr   c              ƒ  ó   "  € R# 5i)zˆOpen a streaming-audio session; returns an opaque handle for the
write/finish/abort calls, or ``None`` to decline (whole-file fallback).Nrt   )rë  rC  rû  r�   s   &&&&r   Úbegin_streaming_ttsÚ'BasePlatformAdapter.begin_streaming_tts:  ó
   é € ñ
 ùrØ  c                ó*   <€ V ^8„  d   QhRS[ RS[RR/# )r   rð  r²  r   N)rw  r¨  )r   rä  s   "€r   r   rà  A  s)   ø€ ÷ Iñ IÑ0Bð IÉ5ð IÐUYñ Ir   c              ƒ  ó   "  € R# 5i)z:Write one PCM chunk to the adapter's outbound audio track.Nrt   )rë  rð  r²  s   &&&r   Úwrite_streaming_ttsÚ'BasePlatformAdapter.write_streaming_ttsA  r×  rØ  Úinterruptedc                ó*   <€ V ^8„  d   QhRS[ RS[RR/# )r   rð  r  r   N)rw  rµ   )r   rä  s   "€r   r   rà  D  s%   ø€ ÷ 5ñ 5Ñ1Cð 5ÑUYð 5Ðfjñ 5r   c             ƒ  ó   "  € R# 5i)z&Signal normal end of the audio stream.Nrt   )rë  rð  r  s   &&$r   Úfinish_streaming_ttsÚ(BasePlatformAdapter.finish_streaming_ttsD  r×  rØ  c                ó:   <€ V ^8„  d   QhRS[ RS[S[,          RR/# )r   rð  r   r   N)rw  rf  r8   )r   rä  s   "€r   r   rà  G  s.   ø€ ÷ cñ cÑ0Bð cÉ8ÑTWÍ=ð cÐdhñ cr   c              ƒ  ó   "  € R# 5i)z«Abort the stream due to an error or cancellation. Must be idempotent: late producer
chunks after abort are silently dropped, not raised. Restores state to "not streaming".Nrt   )rë  rð  r   s   &&&r   Úabort_streaming_ttsÚ'BasePlatformAdapter.abort_streaming_ttsG  r×  rØ  r–   c          	      óN   <€ V ^8„  d   QhRS[ R,          RS[RS[RS[ R,          /# ©r   rú  NÚturn_markerr–   r   ©r8   rg  )r   rä  s   "€r   r   rà  K  s;   ø€ ÷ Mñ M±3¸µ:ð MÉCð MÑbeð MÑqtÐw{Õq{ñ Mr   c               ó   € \        WVR 7      # )r•   )ry  ©rë  rú  r  r–   s   &&&$r   Ú_streaming_tts_turn_keyÚ+BasePlatformAdapter._streaming_tts_turn_keyK  s   € Ü% kÀeÔLÐLr   c                ó>   <€ V ^8„  d   QhRS[ R,          RS[RS[RR/# r  r  )r   rä  s   "€r   r   rà  N  s:   ø€ ÷ Rñ R¹cÀD½jð RÑWZð RÑmpð Rð  }Añ Rr   c               óx   € V P                  WVR 7      pVe#   \        V R\        4      P                  V4       R# R# )r•   Nr  )r  rÝ  r&  r©  )rë  rú  r  r–   Úturn_keys   &&&$ r   Ú"_mark_streaming_tts_completed_turnÚ6BasePlatformAdapter._mark_streaming_tts_completed_turnN  s;   € Ø×/Ñ/°ÐPUÐ/ÓVˆØÒÜ�tÐ=¼sÓC×GÑGÈÖQñ  r   c                ó@   <€ V ^8„  d   QhRS[ R,          RS[RS[RS[/# r  ©r8   rg  rµ   )r   rä  s   "€r   r   rà  S  s6   ø€ ÷ kñ k¹¸t½ð kÑRUð kÑhkð kÑw{ñ kr   c               óD   € \        \        V R \        4       4      WVR7      # )r  r•   )rx  ro   r&  r  s   &&&$r   Ú_streaming_tts_turn_completedÚ1BasePlatformAdapter._streaming_tts_turn_completedS  s%   € Ü3Ü�DÐ:¼C»EÓBÀKÐdiôkð 	kr   c                ó„   <€ V ^8„  d   QhRS[ RS[ RS[S[ ,          RS[S[ ,          RS[S[S[ S[3,          ,          RS[/# )r   rC  Ú
video_pathr   rß  r�   r   rà  )r   rä  s   "€r   r   rà  W  sZ   ø€ ÷ Uñ UÙðUÙ(+ðUÙ6>¹sµmðUá™3•-ðUá2:¹4ÁÁSÀ½>Õ2JðUá`jñUr   c           	   ‹  óH   "  € V P                  RRW!W4V4      G Rj  x€L
 #  L5i)zJSend a video natively (inline playable). Default: friendly failure notice.Ú
send_videor¨   NrÌ  )rë  rC  r$  r   rß  r�   rª  s   &&&&&&,r   r&  ÚBasePlatformAdapter.send_videoW  s3   é € ð ×5Ñ5Ø˜' :¸È8óU÷ Uð 	Uñ Uùr(  c                óš   <€ V ^8„  d   QhRS[ RS[ RS[S[ ,          RS[S[ ,          RS[S[ ,          RS[S[S[ S[3,          ,          RS[/# )r   rC  Ú	file_pathr   r¬   rß  r�   r   rà  )r   rä  s   "€r   r   rà  ^  sf   ø€ ÷ kñ k©3ð k¹3ð kÉÑRUÍð kÙ'/±¥}ðkÙGOÑPSÅ}ðká&.©t±C¹°H­~Õ&>ðkáT^ñkr   c              ‹  óJ   "  € V P                  RRW!W5WdR7      G Rj  x€L
 #  L5i)z@Send a document/file natively. Default: friendly failure notice.Úsend_documentr  )r¬   NrÌ  )rë  rC  r)  r   r¬   rß  r�   rª  s   &&&&&&&,r   r+  Ú!BasePlatformAdapter.send_document^  s8   é € ð ×5Ñ5Ø˜V Y¸ÈHð 6ó k÷ kð 	kñ kùrù  r³   c                ó\   <€ V ^8„  d   QhRS[ RS[ RS[RS[S[S[ S[3,          ,          RR/# )r   rC  Ú
media_pathr³   r�   r   N)r8   rµ   rf  r|   rg  )r   rä  s   "€r   r   rà  e  sI   ø€ ÷ fñ fÙðfÙ(+ðfÙ:>ðfá™4¡¡S �>Õ*ðfà6:ñfr   c             ƒ  ó<  "  € \        V4      P                  P                  4       pV'       g   \        V P                  WSR7      '       d   \        R4      pM@V\        9   d   \        R4      pM)\        R\        P                  P                  V4      4      p V P                  WVR7      G Rj  x€L
 pVe   VP                  '       d   RMVP                  pVe$   \        P                  RV P                   V4       R# R#  LQ  \         d   p	T	p Rp	?	L=Rp	?	ii ; i5i)aš  User-visible notice when a MEDIA attachment upload failed: the tag was
already stripped from the text, so silence would be a silent drop.

The non-streaming dispatch loop strips ``MEDIA:`` tags before sending attachments. When the
subsequent upload returns ``success=False`` (for example Discord accepted the message but attached
nothing), the user must see a failure notice instead of a silent drop (#66797).
©r³   r§   r¨   r  rÃ  Nz5[%s] Could not send media-delivery-failure notice: %s)rb  r>   rp   rº   rq   r°   Ú_VIDEO_EXTSrP   r6   ÚbasenamerÛ  rK  r   r[   r   r«  rF  )
rë  rC  r.  r³   r�   r²   r   rÞ  ÚproblemÚ
notify_errs
   &&&$$     r   Ú_notify_media_delivery_failureÚ2BasePlatformAdapter._notify_media_delivery_failuree  sß   é € ô �:Ó×%Ñ%×+Ñ+Ó-ˆßÔ1°$·-±-À×XÓXÜ& wÓ/‰DØ”KÔÜ& wÓ/‰Dä& v¬r¯w©w×/?Ñ/?À
Ó/KÓLˆDð	!Ø×,Ñ,¨WÀXÐ,ÓN×NˆFØ$šn°··°‘dÀFÇLÁLˆGð ÒÜ�L‰LÐPÐRV×R[ÑR[Ð]dÖeñ ñ	 Oøäô 	!Ø �Gûð	!üsH   ‚BDÂD Â.D Â/D Ã	D Ã)DÄ D ÄDÄDÄDÄDÄDc                ó„   <€ V ^8„  d   QhRS[ RS[ RS[S[ ,          RS[S[ ,          RS[S[S[ S[3,          ,          RS[/# )r   rC  rœ  r   rß  r�   r   rà  )r   rä  s   "€r   r   rà  ~  sZ   ø€ ÷ Zñ ZÙðZÙ(+ðZÙ6>¹sµmðZá™3•-ðZá2:¹4ÁÁSÀ½>Õ2JðZá`jñZr   c           	   ‹  óH   "  € V P                  RRW!W4V4      G Rj  x€L
 #  L5i)zTSend a local image file natively (send_image takes a URL). Default: friendly notice.r¢  r©   NrÌ  )rë  rC  rœ  r   rß  r�   rª  s   &&&&&&,r   r¢  Ú#BasePlatformAdapter.send_image_file~  s4   é € ð ×5Ñ5Ø˜w¨
¸WÐPXóZ÷ Zð 	Zñ Zùr(  c                ó<   <€ V ^8„  d   QhRS[ RS[ RS[S[ ,          /# rH  rI  )r   rä  s   "€r   r   rà  †  s,   ø€ ÷ Kñ K©3ð K¹Sð KÉ(ÑSVÍ-ñ Kr   c                ó   € \        WR7      # )zBReturn a resolved path if it is safe for native attachment upload.rK  )rQ  )r6   rú  s   &&r   rQ  Ú0BasePlatformAdapter.validate_media_delivery_path…  s   € ô ,¨DÔJÐJr   c          	      ór   <€ V ^8„  d   QhRS[ RS[S[S[,          ,          RS[S[S[ S[3,          ,          /# )r   rú  r[  r   )r8   rf  r$  r|   r%  rµ   )r   rä  s   "€r   r   rà  ‹  sD   ø€ ÷ rñ r¹cð rÙ-5±d¹4µjÕ-AðrÙMQÑRWÑX[Ñ]aÐXaÕRbÕMcñrr   c           
     ó’   € T ;'       g    .  UUu. uF)  w  r4\        W1RV4      ;p'       g   K  V\        V4      3NK+  	  upp# u uppi )zWDrop unsafe MEDIA paths and normalize accepted paths; ``dropped`` collects the rejects.zMEDIA directive path)rb  rµ   )r)  rú  r[  r.  r³   ra  s   &&&   r   Úfilter_media_delivery_pathsÚ/BasePlatformAdapter.filter_media_delivery_pathsŠ  s_   € ð
 EP×DUÐDUÐSUÐDUôrÙDUÑ,@¨JÜ5°jÐOeÐgnÓoÐo�	Óoô (ˆYœ˜X›Ó'ÑDUòrð 	rùó rs
   �A®Ac                ó6   <€ V ^8„  d   QhRS[ RS[S[ ,          /# rù  rû  )r   rä  s   "€r   r   rà  “  s   ø€ ÷ ,ñ ,¹Sð ,É$ÉsÍ)ñ ,r   c                óp   a€ V3R lT ;'       g    .  4       pV Uu. uF  q3'       g   K  VNK  	  up# u upi )z?Drop unsafe bare local file paths and normalize accepted paths.c              3   ó>   <"  € T F  p\        VSR 4      x € K  	  R# 5i)zlocal file pathN)rb  )rì   rm  rú  s   & €r   rï   ÚBBasePlatformAdapter.filter_local_delivery_paths.<locals>.<genexpr>•  s"   øé € ÐlÑ[kÐVWÔ.¨q°+Ð?P×QÐQÓ[kùs   ƒrt   )Ú
file_pathsrú  Ú
safe_pathsrm  s   &f  r   Úfilter_local_delivery_pathsÚ/BasePlatformAdapter.filter_local_delivery_paths’  s9   ø€ ô mÐ[e×[kÐ[kÐikÐ[kÓlˆ
Ù%Ó+™:�a«—�™:Ñ+Ð+ùÒ+s   œ	3ª3c                ó&   <€ V ^8„  d   QhRS[ RS[ /# r¿  rk   )r   rä  s   "€r   r   rà  ™  s   ø€ ÷ ,ñ ,¡sð ,©sñ ,r   c           
     óâ  € \         P                  V 4       Uu. uF  qP                  4       NK  	  pp\        P                  V 4       FÚ  pVP	                  4       p\
        P                  ! RV \        ^ V^,
          4      V 4      '       d   KF  VP                  ^ 4      ^R P                  4       pVP                  4       P                  R4      '       d.   \        VR,          4      pV'       d   \        V4      '       d   Kº  VP                  W1P                  4       34       KÜ  	  VP!                  R \
        P                  ! RV \
        P"                  4       4       4       \%        W4      # u upi )z·Blank fenced code, inline code and blockquotes (length-preserving so regex offsets stay
valid) against MEDIA: false positives; backtick-quoted paths inside MEDIA: tags stay
scannable.z
MEDIA:\s*$r‡  :r×  NNc              3   ó@   "  € T F  qP                  4       x € K  	  R # 5ir¼  )r½  )rì   r&  s   & r   rï   Ú<BasePlatformAdapter._mask_protected_spans.<locals>.<genexpr>«  s   é € ÐTÑ'S !—V‘V—X�XÓ'Sùs   ‚z^>.*$rˆ  )rÁ  rµ  r½  rÂ  r‹  r�  Úsearchr¯  r‰  r‹   Úupperr=  rM  rQ  r­  rŠ  r“  Ú	MULTILINEr©  )r  r&  r°  r‹  Úinnerr)  s   &     r   r¨  Ú)BasePlatformAdapter._mask_protected_spans˜  s  € ô
 *9×)AÑ)AÀ'Ô)JÓKÑ)J A—v‘v–xÑ)JˆÐKÜ ×)Ñ)¨'Ö2ˆAØ—G‘G“IˆEÜ�yŠy˜¨´°A°u¸rµzÓ0BÀ5Ð(I×JÒJÙð —G‘G˜A“J˜q Ð$×*Ñ*Ó,ˆEØ�{‰{‹}×'Ñ'¨×1Ò1Ü5°e¸BµiÓ@�	ßÔ!=¸i×!HÒ!HÙØ�L‰L˜%§¡£Ð)Ö*ñ 3ð 	�‰ÑT¤r§{¢{°8¸WÄbÇlÁlÔ'SÓTÔTÜ˜GÓ+Ð+ùò Ls   ˜E,c                ó&   <€ V ^8„  d   QhRS[ RS[ /# r¿  rk   )r   rä  s   "€r   r   rà  ¯  s   ø€ ÷ ,ñ ,©ð ,±ñ ,r   c           	     ó  € RV 9  g   RV 9  d   V # \         P                  ! RV 4       Uu. uFB  p\         P                  ! RVP                  ^4      4      '       g   K1  VP	                  ^4      NKD  	  pp\        W4      # u upi )a*  Blank ``MEDIA:<bare-path>`` tags inside JSON string *values* (stored tool-result text
like ``{"result": "MEDIA:/x/stale.png"}``) so they are never re-delivered. Only
value-context strings (``:,{[`` before the ``"``) and bare paths (``/``, ``~/``, ``X:\``)
count; ``MEDIA:"..."`` quoted tags and line-start/prose tags are untouched. Offsets
preserved.

Here the ``MEDIA:`` is part of stored text, not an outbound directive, but the bare-path branch of
``MEDIA_TAG_CLEANUP_RE`` would still match it and re-deliver a stale file. (Regression report
#34375.)
Ú"r‡  z$(?<=[:,{\[])\s*"((?:[^"\\\n]|\\.)*)"z MEDIA:\s*(?:~/|/|[A-Za-z]:[/\\]))r�  rµ  rM  r‰  r½  r©  )r  r&  r°  s   &  r   r§  Ú+BasePlatformAdapter._mask_json_string_media®  s}   € ð �gÔ °Ô!8ØˆNô  "Ÿ{š{Ð+RÐT[Ô\óKÙ\˜!Ü�yŠyÐ<¸a¿g¹gÀa»j×Iô ˆA�F‰F�1ŽIÑ\ð 	ð Kô ˜GÓ+Ð+ùòKs   ª.A?ÁA?c                ób   <€ V ^8„  d   QhRS[ RS[S[S[S[ S[3,          ,          S[ 3,          /# r¿  )r8   r%  r$  rµ   )r   rä  s   "€r   r   rà  Ä  s3   ø€ ÷ &ñ &™sð &¡u©T±%¹¹T¸	Õ2BÕ-CÁSÐ-HÕ'Iñ &r   c                óv  a	a
a€ . o
RV 9   o	V P                  RR4      P                  RR4      p\        V 4      p\        4       oR V	V
V3R llp\        P	                  V4       FM  p\        VP                  R4      4      pV'       g   K'   V! \        P                  P                  V4      4       KO  	  \        V4       F  w  rgpV! V4       K  	  S
'       dC   \        V4      pV'       d0   \        P                   ! RR\#        W4      4      P%                  4       pS
V3#   \        \        \        3 d     KÕ  i ; i)	a1  Extract ``MEDIA:<path>`` tags and strip ``[[audio_as_voice]]`` / ``[[as_document]]`` ->
``([(path, is_voice), ...], cleaned)``. Both directives are message-global;
``[[as_document]]`` (unmodified sendDocument for large images) is detected by dispatch sites
on the ORIGINAL response and only stripped here.rœ  rn   r�  c                ó(   € V ^8„  d   QhR\         RR/# )r   r6   r   Nrk   )r   s   "r   r   Ú7BasePlatformAdapter.extract_media.<locals>.__annotate__Ö  s   € ÷ 	iñ 	i”sð 	i˜tñ 	ir   c                 óè   <€ V S9  dj   SP                  V 4       SP                  T S;'       d<    \        P                  P	                  V 4      ^,          P                  4       \        9   34       R# R# )r  N)r©  r­  rP   r6   rù  rp   r·   )r6   Úhas_voice_tagr¡  Ú
seen_pathss   &€€€r   Ú_addÚ/BasePlatformAdapter.extract_media.<locals>._addÖ  sX   ø€ à˜:Ô%Ø—‘˜tÔ$Ø—‘˜d M×$fÐ$f´b·g±g×6FÑ6FÀtÓ6LÈQÕ6O×6UÑ6UÓ6WÔ[fÑ6fÐgÖhñ &r   r6   rÃ  r
  )rI   r¬  r&  r¼  rµ  rM  r‰  rP   r6   rƒ  r^   rÍ  rñ   r¶  r±  r�  r¼  rÎ  r‹   )r  rÑ  Úscan_contentr]  rí  r6   rí   ra  r°  r[  r¡  r\  s   &        @@@r   Úextract_mediaÚ!BasePlatformAdapter.extract_mediaÃ  s  ú€ ð ˆØ,°Ñ7ˆØ—/‘/Ð"6¸Ó;×CÑCÐDUÐWYÓZˆô -¨WÓ5ˆô ›%ˆ
÷	iò 	iô
 *×2Ñ2°<Ö@ˆEÜ,¨U¯[©[¸Ó-@ÓAˆDß‰tðÙœŸ™×+Ñ+¨DÓ1Ö2ñ	 Aô  <¸LÖI‰OˆA˜!Ù�ŽOñ  J÷ Ü*¨7Ó3ˆEßÜŸ&š& ¨F´MÀ'Ó4QÓR×XÑXÓZ�Ø�gˆ~Ðøô  ¤¬zÐ:ô Úðús   Â
%DÄD8Ä7D8c                ó&   <€ V ^8„  d   QhRS[ RS[ /# rš  rk   )r   rä  s   "€r   r   rà  í  s   ø€ ÷ Uñ U±ð U¹ñ Ur   c                ó†   € \        V 4      '       g   V # \        P                  ! RR\        V 4      4      P	                  4       # )zùStrip MEDIA: directives from streamed/display text. Known-extension tags are
removed unconditionally (as ``MEDIA_TAG_CLEANUP_RE``); extension-less tags only when
``validate_media_delivery_path`` accepts the path, so undeliverable paths stay visible.rÃ  r
  )rŸ  r�  r¼  rÒ  r<  rž  s   &r   Ú"strip_media_directives_for_displayÚ6BasePlatformAdapter.strip_media_directives_for_displayì  s6   € ô
 % T×*Ò*ØˆKÜ�vŠv�i Ô)DÀTÓ)JÓK×RÑRÓTÐTr   c                óL   <€ V ^8„  d   QhRS[ RS[S[S[ ,          S[ 3,          /# r¿  r¹  )r   rä  s   "€r   r   rà  ö  s,   ø€ ÷ Hñ H¡Sð H©U±4¹µ9¹c°>Õ-Bñ Hr   c                óN  a€ RP                  R \         4       4      p\        P                  ! RV,           R,           \        P                  4      p\        V 4      p/ pVP                  V 4       FÌ  o\        ;QJ d    V3R lV 4       F  '       g   K   RM	  RM! V3R lV 4       4      '       d   KE  SP                  ^ 4      p\        P                  P                  V4      p\        P                  P                  V4      '       d   VP                  We4       K­  \        P                  R\!        V4      4       KÎ  	  V'       g   . V 3# T pVP#                  4        F  pVP%                  VR	4      pK  	  \'        V4      \        P(                  ! R
RV4      P+                  4       3# )a@  Bare local file paths (absolute, ``~/`` or drive-letter) with deliverable extensions ->
``(expanded_paths, cleaned_text)``. Candidates must exist on disk (URLs / hallucinated paths
ignored); paths inside fenced or inline code are skipped so code samples are never
mutilated. Dispatch by type lives in ``gateway/run.py``.ry  c              3   óB   "  € T F  qP                  R 4      x € K  	  R# 5ir{  r|  r~  s   & r   rï   Ú:BasePlatformAdapter.extract_local_files.<locals>.<genexpr>û  s   é € ÐGÑ3F¨aŸH™H SŸM˜MÓ3Fùr€  zB(?<![/:\w.])(?:~/|/|[A-Za-z]:[/\\])(?:[\w.\-]+[/\\])*[\w.\-]+\.(?:z)\bc              3   óp   <"  € T F+  w  rVSP                  4       u;8*  ;'       d    V8  Mu x € K-  	  R # 5ir¼  rº  )rì   rÐ   r  rí  s   &  €r   rï   ri    s)   øé € ÐA±j©d¨a�1˜Ÿ™›×)Ô)¨×)Ñ)³jùs   ƒ36TFz6Skipping bare file path in reply (no file on disk): %srn   rÃ  r
  )rÆ   r—  r�  ÚcompileÚ
IGNORECASErÄ  rµ  rö   r‰  rP   r6   rƒ  ÚisfileÚ
setdefaultr   rÊ  r-  r�  rI   r$  r¼  r‹   )	r  Úext_partÚpath_reÚ
code_spansÚuniquerî  rN  rÑ  rí  s	   &       @r   Úextract_local_filesÚ'BasePlatformAdapter.extract_local_filesõ  s=  ø€ ð —8‘8ÑGÕ3FÓGÓGˆô
 —*’*ØQÐT\Õ\Ð_eÕeÜ�M‰Móˆô ! Ó)ˆ
ØˆØ×%Ñ% gÖ.ˆEß‹sÔA±jÓA�s�sŠsÔA±jÓA×AÒAÙØ—+‘+˜a“.ˆCÜ—w‘w×)Ñ)¨#Ó.ˆHÜ�w‰w�~‰~˜h×'Ò'Ø×!Ñ! (Ö0ô —‘ÐTÔVdÐehÓViÖjñ /÷ Ø�w�;ÐØˆØ—=‘=–?ˆCØ—o‘o c¨2Ó.ŠGñ #ä�F‹|œRŸVšV I¨v°wÓ?×EÑEÓGÐGÐGr   c                óR   <€ V ^8„  d   QhRS[ RS[RS[P                  R,          RR/# )r   rC  ÚintervalÚ
stop_eventNr   )r8   r¨  r   ÚEvent)r   rä  s   "€r   r   rà    s:   ø€ ÷ &Fñ &F©#ð &F¹ð &FÙ'.§}¡}°tÕ';ð&FØGKñ&Fr   c              ƒ  ój  "  € \        R\        RVR,
          4      4      p  Vet   VP                  4       '       d^    V P                  W4      G Rj  x€L
  V P                  P                  V4       \        V R/ 4      P                  \        V4      R4       R# WP                  9  d2    \        P                  ! V P                  WR7      VR7      G Rj  x€L
  Vf!   \        P"                  ! V4      G Rj  x€L
  KÝ  \        P$                  ! 4       pVP'                  4       V,           pVP                  4       '       d   EK"  W‡P'                  4       ,
          p	V	^ 8:  d   EKB  \        P"                  ! \        RV	4      4      G Rj  x€L
  Kc   EL< Lº  \         d     LÅ\         d,   p\        P                  RT P                   T4        Rp?LõRp?ii ; i Lß LR  \        P(                   d     Mi ; iT P                  Y4      G Rj  x€L 
  T P                  P                  T4       \        T R/ 4      P                  \        T4      R4       R#   T P                  Y4      G Rj  x€L 
  T P                  P                  T4       \        T R/ 4      P                  \        T4      R4       i ; i5i)ug  Refresh the typing indicator every ``interval`` seconds until cancelled (platform typing
state expires after ~5s). Chats in ``_typing_paused`` are skipped (approval waits â€” Slack's
setStatus disables the compose box). Each ``send_typing`` is bounded by a sub-interval
timeout so one slow round-trip is abandoned before the next tick, not the bubble lapsing.ç      Ð?r  Nrâ  rÃ  rÅ  z&[%s] send_typing error (non-fatal): %s)r¯  rZ  Úis_setÚ_stop_typing_quietlyr  r´  ro   rã  r8   r   rÍ  r}  rÏ  r[   r   r«  rF  r  rÉ  r  r¶  )
rë  rC  rv  r�   rw  Ú_send_typing_timeoutÚ
typing_errrÀ  ÚdeadlineÚ	remainings
   &&&&&     r   Ú_keep_typingÚ BasePlatformAdapter._keep_typing  s7  é € ô  # 4¬¨S°(¸Tµ/Ó)BÓCÐð	FØØÒ)¨j×.?Ñ.?×.AÒ.AØð2 ×+Ñ+¨GÓ>×>Ð>Ø×Ñ×'Ñ'¨Ô0ä�D˜.¨"Ó-×1Ñ1´#°g³,ÀÖEð7 ×"5Ñ"5Ô5ðfÜ%×.Ò.¨t×/?Ñ/?ÀÐ/?Ó/[Ø7KôM÷ Mð Mð Ò%Ü!Ÿ-š-¨Ó1×1Ð1ÙÜ×/Ò/Ó1�ØŸ9™9›;¨Õ1�Ø$×+Ñ+×-Õ-Ø (¯9©9«;Õ 6�IØ  A”~Úô "Ÿ-š-¬¨D°)Ó(<Ó=×=Ò=ò
 ?ñ-Møä'ô ÙÜ$ô fÜŸ™Ð%MÈtÏyÉyÐZd×eÑeûðfúñ 2ñ >øÜ×%Ñ%ô 	Ùð	úð ×+Ñ+¨GÓ>×>Ñ>Ø×Ñ×'Ñ'¨Ô0ä�D˜.¨"Ó-×1Ñ1´#°g³,ÀÖEøð ×+Ñ+¨GÓ>×>Ñ>Ø×Ñ×'Ñ'¨Ô0ä�D˜.¨"Ó-×1Ñ1´#°g³,ÀÕEüsà   ‚J3¡G ½J3ÁFÁAJ3ÂG Â*+F ÃFÃF ÃG Ã7GÃ8AG ÅAG ÆGÆG ÆJ3ÆF ÆGÆG ÆGÆ(GÆ)!GÇ
G ÇGÇG ÇG ÇG3Ç0I Ç2G3Ç3I Ç6J3È
HÈAJ3ÉJ0É(I+É)AJ0Ê0J3r3   g      à?Ústop_attemptsc          
      óX   <€ V ^8„  d   QhRS[ RS[P                  R,          RS[RS[RR/# )r   rC  Útyping_taskNr3   rƒ  r   )r8   r   r   r¨  r9   )r   rä  s   "€r   r   rà  >  s>   ø€ ÷ 1ñ 1Ùð1Ù)0¯©¸Õ)<ð1áð1á-0ð1à9=ñ1r   c             ƒ  óè  "  € V P                   P                  V4        VeŸ   VP                  4       '       g‰   VP                  4        \        P
                  ! \        P                  \        P                  4      ;_uu_ 4        \        P                  ! \        P                  ! V4      VR7      G Rj  x€L
  RRR4       \        \        ^V4      4       FB  pV'       d   \        P                  ! ^ 4      G Rj  x€L
  V P                  W4      G Rj  x€L
  KD  	  V P                   P                  V4       R#  L„  + '       g   i     LŠ; i LS L<  T P                   P                  T4       i ; i5i)zAStop the refresh task and platform typing state as one operation.NrÅ  )r  r©  r  r  r\   r]   r   r¶  rÏ  rÍ  rµ  r  r¯  r  r|  r´  )rë  rC  r…  r�   r3   rƒ  r  s   &&&$$$ r   Ú_stop_typing_refreshÚ(BasePlatformAdapter._stop_typing_refresh>  s  é € ð 	×Ñ×Ñ Ô(ð	1ØÒ&¨{×/?Ñ/?×/AÒ/AØ×"Ñ"Ô$ä×(Ò(¬×)?Ñ)?Ä×AUÑAU×VÕVÜ!×*Ò*¬7¯>ª>¸+Ó+FÐPWÔX×XÐX÷ Wä ¤ Q¨Ó!6Ö7�ßÜ!Ÿ-š-¨Ó*×*Ð*Ø×/Ñ/°ÓB×BÒBñ 8ð
 ×Ñ×'Ñ'¨Ö0ñ Y÷ W×Vúñ +ÙBøà×Ñ×'Ñ'¨Õ0üsk   ‚E2ŸE ¹AE Â0D;Â4D9Â5D;Â9AE Ã:EÃ;E ÄEÄE ÄE2Ä9D;Ä;E	Å	E ÅE ÅE/Å/E2c                ó$   <€ V ^8„  d   QhRS[ RR/# rz  rk   )r   rä  s   "€r   r   rà  P  s   ø€ ÷ Eñ E±#ð EÈñ Er   c              ƒ  óÂ   "  € \         P                  ! \        4      ;_uu_ 4        V P                  W4      G Rj  x€L
  RRR4       R#  L  + '       g   i     R# ; i5i)z?Best-effort platform stop_typing; adapter errors are swallowed.N)r\   r]   r[   r”  r|  s   &&&r   r|  Ú(BasePlatformAdapter._stop_typing_quietlyP  s@   é € ä× Ò ¤×+Õ+Ø×1Ñ1°'ÓD×DÐD÷ ,Ñ+ÙD÷ ,×+Ð+üs+   ‚#A¥AºA	»A¿
AÁ	AÁA	Á	Ac                ó$   <€ V ^8„  d   QhRS[ RR/# rz  rk   )r   rä  s   "€r   r   rà  U  s   ø€ ÷ )ñ )©Sð )°Tñ )r   c                ó<   € V P                   P                  V4       R# )zNPause typing for a chat (approval waits); GIL-safe from the sync agent thread.N)r  r©  r  s   &&r   Úpause_typing_for_chatÚ)BasePlatformAdapter.pause_typing_for_chatU  s   € à×Ñ×Ñ Ö(r   c                ó$   <€ V ^8„  d   QhRS[ RR/# rz  rk   )r   rä  s   "€r   r   rà  Y  s   ø€ ÷ -ñ -©cð -°dñ -r   c                ó<   € V P                   P                  V4       R# )z;Resume typing indicator for a chat after approval resolves.N)r  r´  r  s   &&r   Úresume_typing_for_chatÚ*BasePlatformAdapter.resume_typing_for_chatY  s   € à×Ñ×#Ñ# GÖ,r   c                ó*   <€ V ^8„  d   QhRS[ RS[ RR/# )r   rú  rC  r   Nrk   )r   rä  s   "€r   r   rà  ]  s#   ø€ ÷ ;ñ ;¹Cð ;É#ð ;Ðaeñ ;r   c              ƒ  ó¶   "  € V'       d2   WP                   9   d"   V P                   V,          P                  4        V P                  W#4      G Rj  x€L
  R#  L5i)zDSignal the active session loop to stop and clear typing immediately.N)rø  r&  r|  )rë  rú  rC  r�   s   &&&&r   Úinterrupt_session_activityÚ.BasePlatformAdapter.interrupt_session_activity]  s>   é € ç˜;×*?Ñ*?Ô?Ø×!Ñ! +Õ.×2Ñ2Ô4Ø×'Ñ'¨Ó:×:Ô:ùs   ‚AAÁAÁAÚ
generationc                ó>   <€ V ^8„  d   QhRS[ RS[RS[R,          RR/# )r   rú  r  r˜  Nr   r#  )r   rä  s   "€r   r   rà  c  s7   ø€ ÷ Mñ MÙðMÙ*2ðMÙCFÈÅ:ðMØY]ñMr   c               ó   € V'       d   \        V4      '       g   R# V P                  P                  V4      pVet   \        V4      w  rVVe    Ve   \	        V4      \	        V4      8  d   R# \        V4      '       d3   Ve   Ve   \	        V4      \	        V4      8X  d   V P                  Wb4      pVf   TM\	        V4      V3V P                  V&   R# )u  Register a deferred callback to fire after the main response. Same-key registrations are
chained (both fire in order, per-callback exception isolation) so independent features
coexist; ``generation`` ties it to a gateway run â€” stale generations never overwrite a
fresher slot.N)r;  r  r¥   r×  r9   Ú_chain_callbacks)rë  rú  r  r˜  r   Úexisting_genÚexisting_cbs   &&&$   r   Úregister_post_delivery_callbackÚ3BasePlatformAdapter.register_post_delivery_callbackc  s¹   € ÷ ¤(¨8×"4Ò"4ÙØ×0Ñ0×4Ñ4°[ÓAˆØÒÜ(BÀ8Ó(LÑ%ˆLØÒ'¨JÒ,BÄsÈ:ÃÔY\Ð]iÓYjÔGjÙä˜×$Ò$ØÒ$¨
Ò(:¼cÀ,Ó>OÔSVÐWaÓSbÔ>bØ×0Ñ0°ÓG�à"Ò*‰H´°Z³À(Ð0Kð 	×%Ñ% kÓ2r   c                óH   <€ V ^8„  d   QhRS[ RS[ . S[R,          3,          /# )r   Ú	callbacksr   N)rh  ri  )r   rä  s   "€r   r   rà  x  s)   ø€ ÷ ñ ¡Xð ±(¸2¹yÈ½Ð;NÕ2Oñ r   c                 ó   a € R V 3R llpV# )z™Async wrapper running ``callbacks`` in order with per-callback exception isolation;
async so coroutines returned by async hooks are awaited, not dropped.c                ó   € V ^8„  d   QhRR/# r‘   rt   )r   s   "r   r   Ú:BasePlatformAdapter._chain_callbacks.<locals>.__annotate__{  s   € ÷ 	Qñ 	Q ñ 	Qr   c               “   óØ   <"  € S F3  p  V ! 4       p\         P                  ! V4      '       d   VG R j  x€L
  K3  K5  	  R #  L  \         d    \        P	                  RRR7        K`  i ; i5i)NzPost-delivery callback failedTr   )r‡  Úisawaitabler[   r   r«  )Ú_cbÚ_resultr¡  s     €r   Ú_chainedÚ6BasePlatformAdapter._chain_callbacks.<locals>._chained{  s`   øé € Û �ðQÙ!›e�GÜ×*Ò*¨7×3Ò3Ø%Ÿšñ 4ó !ñ &øÜ ô QÜ—L‘LÐ!@È4�L×PðQüs5   ƒA*Š(A²?³A·A*¿AÁ"A'Á#A*Á&A'Á'A*rt   )r¡  r©  s   j r   r›  Ú$BasePlatformAdapter._chain_callbacksw  s   ø€ ÷	Qð 	Qð ˆr   c                óH   <€ V ^8„  d   QhRS[ RS[R,          RS[R,          /# )r   rú  r˜  Nr   )r8   r9   rh  )r   rä  s   "€r   r   rà  …  s.   ø€ ÷ 
8ñ 
8Ùð
8Ù/2°T­zð
8ÙEMÐPTÅ_ñ
8r   c               ó  € V'       d   V P                   P                  V4      MRpVf   R# \        V4      w  rEVe    Ve   \        V4      \        V4      8w  d   R# V P                   P	                  VR4       \        V4      '       d   V# R# )zCPop a deferred callback, optionally requiring generation ownership.N)r  r¥   r×  r9   rã  r;  )rë  rú  r˜  rò  Úentry_generationr  s   &&$   r   Úpop_post_delivery_callbackÚ.BasePlatformAdapter.pop_post_delivery_callback…  s…   € ÷ CN�×-Ñ-×1Ñ1°+Ô>ÐSWˆØŠ=ÙÜ%?ÀÓ%FÑ"ÐØÒ!Ð'7Ò'?Ä3ÐGWÓCXÔ\_Ð`jÓ\kÔCkÙØ×%Ñ%×)Ñ)¨+°tÔ<Ü# H×-Ò-ˆxÐ7°4Ð7r   c                ó$   <€ V ^8„  d   QhRS[ RR/# r/  r0  )r   rä  s   "€r   r   rà  ˜  s   ø€ ÷ =ñ =©|ð =Àñ =r   c              ƒ  ó   "  € R# 5i)z.Hook called when background processing begins.Nrt   rh  s   &&r   Úon_processing_startÚ'BasePlatformAdapter.on_processing_start˜  r×  rØ  c                ó*   <€ V ^8„  d   QhRS[ RS[RR/# )r   r–   Úoutcomer   N)rz  r|  )r   rä  s   "€r   r   rà  ›  s$   ø€ ÷ 2ñ 2±,ð 2ÑIZð 2Ð_cñ 2r   c              ƒ  ól  "  € V P                   f   V P                  f   R# \        V RR4      p\        V RR4      p\        V RR4      p\        VP                  RR4      p\        VRR4      p\	        V4      '       d@   \	        V4      '       d/   \	        V4      '       d   V! 4       '       d   V'       d	   V'       g   R# V! Wg4      G Rj  x€L
  \
        P                  V P                   \
        P                  V P                  /P                  V4      pV'       d   V! WgV4      G Rj  x€L
  R# R#  Lf L
5i)u^  Hook called when background processing completes. Default: opt-in reaction ack â€” with
``_OK_EMOJI``/``_FAIL_EMOJI`` set and ``_add_reaction``/``_remove_reaction`` present, swap
the in-progress reaction for the outcome one. Remove-then-add is deterministic whether the
platform replaces or stacks a sender's reactions. CANCELLED leaves it unreacted.NÚ_add_reactionÚ_remove_reactionÚ_reactions_enabledrC  r‡   )	Ú	_OK_EMOJIÚ_FAIL_EMOJIro   rŒ   r;  r|  ÚSUCCESSÚFAILUREr¥   )	rë  r–   r¶  r©  r¥  ÚenabledrC  r‡   r[  s	   &&&      r   Úon_processing_completeÚ*BasePlatformAdapter.on_processing_complete›  sü   é € ð
 �>‰>Ò! d×&6Ñ&6Ò&>ÙÜ˜4 °$Ó7ˆÜ˜dÐ$6¸Ó=ˆÜ˜$Ð 4°dÓ;ˆÜ˜%Ÿ,™,¨	°4Ó8ˆÜ˜U L°$Ó7ˆ
Ü˜—’¤X¨f×%5Ò%5¼(À7×:KÒ:KÑT[×T]ÒT]ß§jÙÙ�WÓ)×)Ð)Ü"×*Ñ*¨D¯N©NÜ"×*Ñ*¨D×,<Ñ,<ð>ß>A¹cÀ'»lð 	çÙ�g¨5Ó1×1Ò1ñ ñ 	*ñ 2ùs=   ‚B)D4Â,D4Â4D4Â<D4Ã	D0Ã
AD4ÄD4Ä'D2Ä(	D4Ä2D4c                ó0   <€ V ^8„  d   QhRS[ RS[RS[RR/# )r   Ú	hook_namer^  rª  r   Nr  )r   rä  s   "€r   r   rà  °  s0   ø€ ÷ Oñ O±Cð OÁð OÉsð OÐW[ñ Or   c              �  óæ   "  € \        WR4      p\        V4      '       g   R#  V! V/ VB G Rj  x€L
  R#  L  \         d-   p\        P	                  RT P
                  Y4        Rp?R# Rp?ii ; i5i)zARun a lifecycle hook without letting failures break message flow.Nz[%s] %s hook failed: %s)ro   r;  r[   r   rX   rF  )rë  rÃ  r^  rª  Úhookr  s   &&*,  r   Ú_run_processing_hookÚ(BasePlatformAdapter._run_processing_hook°  s_   é € ä�t¨Ó-ˆÜ˜�~Š~Ùð	OÙ˜Ð' Ñ'×'Ô'øÜô 	OÜ�N‰NÐ4°d·i±iÀ×NÒNûð	Oüs7   ‚ A1£7 ®5¯7 ³A1µ7 ·A.Á!A)Á#A1Á)A.Á.A1c                ó6   <€ V ^8„  d   QhRS[ S[,          RS[/# ©r   r   r   r  )r   rä  s   "€r   r   rà  »  s#   ø€ ÷ Hñ H¡8©C¥=ð H±Tñ Hr   c                ó¼   a€ T ;'       g    RP                  4       o\        ;QJ d#    V3R l\         4       F  '       g   K   R# 	  R# ! V3R l\         4       4      # )zGReturn True if the error string looks like a transient network failure.rn   c              3   ó,   <"  € T F	  qS9   x € K  	  R # 5ir¼  rt   ©rì   ÚpatÚlowereds   & €r   rï   Ú:BasePlatformAdapter._is_retryable_error.<locals>.<genexpr>¾  s   øé € ÐGÑ-F c˜'–>Ó-Fùrj  TF)rp   rö   r}  ©r   rÎ  s   &@r   Ú_is_retryable_errorÚ'BasePlatformAdapter._is_retryable_errorº  sD   ø€ ð —;�;˜B×%Ñ%Ó'ˆß‹sÔGÕ-FÓG�sŒsÐGŠsÐGˆsÔGÕ-FÓGÓGÐGr   c                ó6   <€ V ^8„  d   QhRS[ S[,          RS[/# rÉ  r  )r   rä  s   "€r   r   rà  Á  s#   ø€ ÷ Hñ H¡h©s¥mð H¹ñ Hr   c                ó4   € \        RT ;'       g    R4      R8H  # )zÿReturn True if the error string classifies as a rate limit / flood cap.

Single wrapper around :func:`classify_send_error` so the call sites in
:meth:`_send_with_retry` share one notion of "is this a rate limit" instead
of inline copies that could drift.
Nrn   rV  )r‡  )r   s   &r   Ú_is_rate_limited_errorÚ*BasePlatformAdapter._is_rate_limited_errorÀ  s   € ô # 4¨¯¨°"Ó5¸ÑGÐGr   c                ó6   <€ V ^8„  d   QhRS[ S[,          RS[/# rÉ  r  )r   rä  s   "€r   r   rà  Ë  s#   ø€ ÷ [ñ [¡©#¥ð [±4ñ [r   c                ó¬   a€ T ;'       g    RP                  4       o\        ;QJ d    V3R lR 4       F  '       g   K   R# 	  R# ! V3R lR 4       4      # )u‘   Return True for read/write timeouts â€” NOT retryable and NOT a plain-text
fallback trigger, because the request may already have been delivered.rn   c              3   ó,   <"  € T F	  qS9   x € K  	  R # 5ir¼  rt   rÌ  s   & €r   rï   Ú8BasePlatformAdapter._is_timeout_error.<locals>.<genexpr>Ï  s   øé € ÐZÑ-Y c˜'–>Ó-Yùrj  TF)z	timed outÚreadtimeoutÚwritetimeout)rp   rö   rÐ  s   &@r   Ú_is_timeout_errorÚ%BasePlatformAdapter._is_timeout_errorÊ  sD   ø€ ð —;�;˜B×%Ñ%Ó'ˆß‹sÔZÑ-YÓZ�sŒsÐZŠsÐZˆsÔZÑ-YÓZÓZÐZr   c                óL   <€ V ^8„  d   QhRS[ RS[S[S[,          S[3,          /# )r   r‘  r   )rg  r%  rf  r8   r9   )r   rä  s   "€r   r   rà  Ñ  s)   ø€ ÷ ,ñ ,©#ð ,±%¹Á½ÁsÐ8JÕ2Kñ ,r   c                ó4  a € \        V\        4      '       g   V^ 3# VP                  pVf   \        V 3R l^ \        4      pV'       d1   V^ 8”  d*   \        S 4      P                  \        P                  J d   ^ pVP                  \        T;'       g    ^ 4      3# )a  Unwrap a str/None/:class:`EphemeralReply` response into ``(text, ttl)``. ``ttl > 0``
means schedule ``_schedule_ephemeral_delete`` after a successful send; forced to 0 when the
adapter doesn't override ``delete_message`` so non-supporting platforms degrade to normal
sends.c                  ó6   <€ \        S P                  4       4      # r¼  )r9   rý  r™  s   €r   rš  Ú7BasePlatformAdapter._unwrap_ephemeral.<locals>.<lambda>Ú  s   ø€ ¤c¨$×*PÑ*PÓ*RÔ&Sr   )
r¤   rŒ  rŽ  rw   r[   rA  rö  r¦  r   r9   )rë  r‘  Úttls   f& r   Ú_unwrap_ephemeralÚ%BasePlatformAdapter._unwrap_ephemeralÑ  s|   ø€ ô
 ˜(¤N×3Ò3Ø˜Q�;ÐØ×"Ñ"ˆØŠ;ÜÔSÐUVÔXaÓbˆCß�3˜”7œt D›z×8Ñ8Ô<O×<^Ñ<^Ó^ØˆCØ�}‰}œc #§( (¨›mÐ+Ð+r   Úlog_cmdc                ó:   <€ V ^8„  d   QhRS[ RS[S[,          RR/# )r   r–   ræ  r   N)rz  rf  r8   )r   rä  s   "€r   r   rà  ß  s-   ø€ ÷ ^ñ ^±,ð ^ÉHÑUXÍMð ^Ðeiñ ^r   c             ƒ  ól  "  € \        V4      pV P                  V4      G Rj  x€L
 pV P                  V4      w  rVV'       g   R# VeA   \        P	                  RV P
                  V\        V4      VP                  P                  4       V P                  VP                  P                  V\        V4      \        V4      R7      G Rj  x€L
 pV^ 8”  d\   VP                  '       dH   VP                  '       d4   V P                  VP                  P                  VP                  V4       R# R# R# R#  EL Lk5i)u�   Call the handler and send its reply inline, with retry, threading and
ephemeral deletion â€” no session lifecycle (active-session bypass paths).Nz4[%s] Sending command '/%s' response (%d chars) to %sru  )r—   rë  rä  r   rÊ  rF  rÒ   rŒ   rC  Ú_send_with_retryr”   rœ   rK  r‡   r  )rë  r–   ræ  Úthread_metar‘  r   Úeph_ttlre   s   &&$     r   Ú_dispatch_inline_replyÚ*BasePlatformAdapter._dispatch_inline_replyß  sý   é € ô 1°Ó7ˆØ×.Ñ.¨uÓ5×5ˆØ×.Ñ.¨xÓ8‰ˆßÙØÒÜ�K‰KÐNÐPT×PYÑPYÐ[bÜ˜D›	 5§<¡<×#7Ñ#7ô9à×,Ñ,Ø—L‘L×(Ñ(°$ÔAXÐY^ÓA_Ü*¨;Ó7ð -ó 9÷ 9ˆð �QŒ;˜6Ÿ>Ÿ>˜>¨f×.?×.?Ð.?Ø×+Ñ+¨E¯L©L×,@Ñ,@À&×BSÑBSÐU\Ö]ñ /@™>‰;ò 6ñ9ùs.   ‚ D4¢D/£B#D4ÃD2ÃD4Ã$D4Ã6:D4Ä2D4c                ó0   <€ V ^8„  d   QhRS[ S[,          /# r1  r2  )r   rä  s   "€r   r   rà  ð  s   ø€ ÷ 
,ñ 
,©H±]Õ,Cñ 
,r   c                ó&  € \        V P                  RR4      p\        V4      '       d   Vf   \        P                  ! 4       #  V! V4      #   \
         d;    \        P                  RT P                  RR7       \        P                  ! 4       u # i ; i)z€Routed home + terminal policy for post-handler text, media and error delivery;
a no-op without a runner or outside multiplexing.Ú _media_delivery_scope_for_sourceNz+[%s] Failed to resolve media delivery scopeTr   )	ro   r6  r;  r\   Únullcontextr[   r   r«  rF  )rë  rŒ   rÌ  s   && r   Ú_media_delivery_scopeÚ)BasePlatformAdapter._media_delivery_scopeð  s}   € ô ˜$×-Ñ-Ð/QÐSWÓXˆÜ˜× Ò  F¢NÜ×)Ò)Ó+Ð+ð	,Ù˜6“?Ð"øÜô 	,Ü�L‰LÐFÈÏ	É	Ð\`ˆLÔaÜ×)Ò)Ó+Ò+ð	,ús   ÁA ÁABÂBc                ó4   <€ V ^8„  d   QhRS[ S[,          RR/# )r   rŒ   r   r¦  r2  )r   rä  s   "€r   r   rà  ü  s!   ø€ ÷ ñ ©h±}Õ.Eð ÐJ_ñ r   c                ó8  € \        V P                  RR4      p\        V4      '       g   V #  V! V4      p\        T\        4      '       d   TP                  T P                  8X  d   T# T #   \         d&    \        P                  RT P                  4       T u # i ; i)a  The runner's CURRENT adapter for a new final-response send: a reconnect can swap the
registry adapter mid-task; an unsent final response belongs on the replacement transport,
while message IDs, edits and deletes stay owned by the old one (nothing is migrated).Ú_delivery_adapter_forNz6[%s] Failed to resolve live adapter for final delivery)
ro   r6  r;  r[   r   r«  rF  r¤   r¦  rq   )rë  rŒ   rÌ  Úlive_adapters   &&  r   Ú_final_delivery_adapterÚ+BasePlatformAdapter._final_delivery_adapterü  s’   € ô ˜$×-Ñ-Ð/FÈÓMˆÜ˜× Ò ØˆKð	Ù" 6›?ˆLô �lÔ$7×8Ò8¸\×=RÑ=RÐVZ×VcÑVcÔ=cØÐØˆøô ô 	Ü�L‰LÐQÐSW×S\ÑS\Ô]ØŠKð	ús   ¬A) Á)-BÂBc                óT   <€ V ^8„  d   QhRS[ RS[ RS[S[ ,          RS[RS[RS[RS[/# )r   rC  r  rß  r�   Úmax_retriesÚ
base_delayr   )r8   rf  rg  r9   r¨  rI  )r   rä  s   "€r   r   rà    sR   ø€ ÷ xñ xÙðxÙ%(ðxÙ4<¹SµMðxÙTWðxáðxá*/ðxá:Dñxr   c           	   ƒ  óÞ  a aaaaa"  € R VVVV 3R lloR VVVVVV 3R llpS! S4      G Rj  x€L
 pVP                   '       g   S P                  V4      '       d   V# VP                  ;'       g    Rp	S P                  V	4      p
VP                  ;'       g2    T
;'       g(    VP
                  RJ;'       g    S P                  V	4      pV'       g   S P                  V	4      '       d   V# V'       Ed|   VP
                  p\        ^V^,           4       EFÐ  pTpVf   V^V^,
          ,          ,          pM6V\        8”  d,   \        P                  RS P                  V\        V	4       Vu # V\        P                  ! ^ ^4      ,           pRp\        P                  RS P                  WÕWù4       \        P                   ! V4      G Rj  x€L
  V! V4      G Rj  x€L
 pVf&   \        P                  R	S P                  V	4       Vu # TpVP                   '       d&   \        P#                  R
S P                  V4       Vu # VP                  ;'       g    Rp	S P                  V4      '       d   Vu # VP
                  e   VP
                  pS P                  V	4      p
VP                  '       d   EK›  V
'       d   EK¦  VP
                  e   EK·  S P                  V	4      '       d   EKÑ   M‰	  S P                  V	4      '       g   VP
                  e$   \        P                  RS P                  V	4       V# \        P                  RS P                  WY4       \%        R4      p S! V4      G Rj  x€L
  V# S P+                  V4      '       d$   \        P                  RS P                  V	4       V# \        P                  RS P                  V	4       S P-                  SSSSR7      G Rj  x€L
 pVP                   '       g,   \        P                  RS P                  VP                  4       V#  ELø ELc ELV LÆ  \&         d-   p\        P)                  RS P                  T4        Rp?T# Rp?ii ; i Lˆ5i)z–Send with exponential-backoff retry on transient network errors; permanent
failures fall back to a plain-text send, exhausted retries notify the user.c                ó0   € V ^8„  d   QhR\         R\        /# rš  rß  )r   s   "r   r   Ú:BasePlatformAdapter._send_with_retry.<locals>.__annotate__  s   € ÷ 	hñ 	hœcð 	h¤jñ 	hr   c              “   óJ   <"  € SP                  SV SSR 7      G Rj  x€L
 #  L5i)ru  Nrv  )r   rC  r�   rß  rë  s   &€€€€r   Ú_sendÚ3BasePlatformAdapter._send_with_retry.<locals>._send  s$   øé € ØŸ™¨7¸DÈ8Ð^f˜Óg×gÐgÑgùs   ƒ#œ!�#c                óF   € V ^8„  d   QhR\         R\        \         ,          /# )r   Úpreviousr   )rI  rf  )r   s   "r   r   rÿ    s#   € ÷ 	lñ 	l¬
ð 	l´xÄ
Õ7Kñ 	lr   c              “  óœ   <"  € SP                  V 4      '       g   S! S4      G Rj  x€L
 # SP                  SV SSR7      G Rj  x€L
 #  L! L5i)u  Retry: the whole payload normally; only the undelivered remainder after a partial split
delivery (``raw_response["partial_overflow"]``). ``None`` when the adapter cannot resume â€” the
caller then keeps the partial failure rather than re-sending the already-visible head.NrÙ  )Ú_is_partial_deliveryÚ_resume_partial_send)r	  r	  rC  r  r�   rß  rë  s   &€€€€€€r   Ú_send_againÚ9BasePlatformAdapter._send_with_retry.<locals>._send_again  sL   øé € ð ×,Ñ,¨X×6Ò6Ù" 7›^×+Ð+Ø×2Ñ2°7¸HÈxÐbjÐ2Ók×kÐkñ ,Ùkùs!   ƒ#A¦A§AÁA
ÁAÁ
ANrn   z{[%s] Server asked to retry after %.0fs (> %.0fs inline cap); returning typed failure for redelivery instead of sleeping: %sz7[%s] Send failed (attempt %d/%d, retrying in %.1fs): %sz”[%s] Split send partly delivered and the remainder cannot be resumed safely; not re-sending the whole payload (would duplicate the visible head): %sz[%s] Send succeeded on retry %dz�[%s] Rate-limited send exhausted retries; returning typed failure for redelivery (no notice sent inside active flood penalty): %sz4[%s] Failed to deliver response after %d retries: %sz$gateway.notify.delivery_failed_retryz/[%s] Could not send delivery-failure notice: %suL   [%s] Send failed after partial delivery: %s â€” not re-sending as plain textu3   [%s] Send failed: %s â€” trying plain-text fallbackrÙ  z"[%s] Fallback send also failed: %s)rK  Ú_send_retry_is_finalr   rÕ  rM  rN  rÑ  rÝ  r  Ú _SEND_RETRY_INLINE_WAIT_CAP_SECSr   rF  ÚrandomÚuniformrX   r   r  rÊ  r   r[   r«  r	  Ú_send_plain_fallback)rë  rC  r  rß  r�   rû  rü  r	  re   Ú	error_strÚis_rate_limitedÚ
is_networkÚserver_retry_afterr  ÚbackoffÚdelayÚresumedrÞ  r4  Úfallback_resultr	  s   fffff&&             @r   ré  Ú$BasePlatformAdapter._send_with_retry  sÙ  ýé € ÷	hó 	h÷	lõ 	lñ ˜W“~×%ˆØ�>�>ˆ>˜T×6Ñ6°v×>Ò>ØˆMØ—L‘L×&Ð& Bˆ	ð ×5Ñ5°iÓ@ˆà×Ñ÷ 3ð 3Ø÷3ð 3à×!Ñ!¨Ð-÷3ð 3ð ×'Ñ'¨	Ó2ð	 	÷ ˜d×4Ñ4°Y×?Ò?ØˆMßˆ:à!'×!3Ñ!3ÐÜ   K°!¥O×4�Ø,�Ø’?Ø(¨A°'¸Aµ+Õ,>Õ?‘GØÔ?Ô?ô —L‘LðOàŸ	™	 7Ô,LÈiôð
 "’MØ¤&§.¢.°°AÓ"6Õ6�Ø%)Ð"Ü—‘ÐXÐZ^×ZcÑZcØ&°UôGä—m’m EÓ*×*Ð*Ù +¨FÓ 3×3�Ø’?Ü—N‘NðbØcg×clÑclÐnwôyð "’MØ �Ø—>—>�>Ü—K‘KÐ AÀ4Ç9Á9ÈgÔVØ!’MØ"ŸL™L×.Ð.¨B�	Ø×,Ñ,¨V×4Ò4Ø!’MØ×%Ñ%Ò1Ø)/×);Ñ);Ð&ð #'×"=Ñ"=¸iÓ"H�à×$×$Ó$ß&’Ø×)Ñ)Õ5Ø×/Ñ/°	×:Õ:áñ] 5ðn ×.Ñ.¨y×9Ò9¸V×=OÑ=OÒ=[Ü—L‘LðZàŸ	™	 9ôð
 "�MÜ—‘ÐSÐUY×U^ÑU^Ð`kÔwäÐAÓB�ðkÙ ›-×'Ð'ð �ð ×$Ñ$ V×,Ò,ä�N‰NÐiÐko×ktÑktÐvô  AØˆMÜ�‰ÐLÈdÏiÉiÐYbÔcØ $× 9Ñ 9¸'À7ÐU]ÐhpÐ 9Ó q×qˆØ×&×&Ð&Ü�L‰LÐ=¸t¿y¹yÈ/×J_ÑJ_Ô`ØÐòQ &òR +Ú3ñ^ (øÜ ô kÜ—L‘LÐ!RÐTX×T]ÑT]Ð_i×jÐjØ�ûðkúñ rùsñ   ˆ&Q-®P&¯Q-ÁQ-ÁQ-Á1&Q-Â	Q-Â"Q-Â8Q-ÃQ-Ã)
Q-Ã4CQ-ÇP)ÇQ-ÇP,ÇA Q-È7Q-ÉQ-É*>Q-Ê.Q-Ê9Q-Ë
Q-Ë$Q-Ë?AQ-ÍP1 Í(P/Í)P1 Í-Q-ÎAQ-Ï"Q+Ï#Q-Ï9.Q-Ð)Q-Ð,Q-Ð/P1 Ð1Q(Ð<!Q#ÑQ-Ñ#Q(Ñ(Q-c                ó&   <€ V ^8„  d   QhRS[ RS[/# ©r   re   r   ©rI  rµ   )r   rä  s   "€r   r   rà  ‡  s   ø€ ÷ ñ ©:ð ¹$ñ r   c                ó   € R# )zšTrue when a failed send must be returned as-is: neither a retry nor the plain-text
fallback can fix it (a structured auth/target refusal). Default: never.Frt   )rë  re   s   &&r   r
	  Ú(BasePlatformAdapter._send_retry_is_final‡  r8  r   c                ó&   <€ V ^8„  d   QhRS[ RS[/# r	  r	  )r   rä  s   "€r   r   rà  �  s   ø€ ÷ Kñ K¡Zð K±Dñ Kr   c                ó€   € \        V RR4      p\        V\        4      ;'       d    \        VP	                  R4      4      # )zÕTrue when a split payload was PARTLY delivered (``raw_response["partial_overflow"]``, the
contract Telegram's send/edit-overflow paths set and the stream consumer reads): the visible
head must never be sent again.rL  NÚpartial_overflow)ro   r¤   r|   rµ   r¥   )re   rî  s   & r   r	  Ú(BasePlatformAdapter._is_partial_deliveryŒ  s6   € ô
 �f˜n¨dÓ3ˆÜ˜#œtÓ$×JÐJ¬¨c¯g©gÐ6HÓ.IÓ)JÐJr   c                óX   <€ V ^8„  d   QhRS[ RS[RS[S[ ,          RS[RS[S[,          /# )r   rC  re   rß  r�   r   )r8   rI  rf  rg  )r   rä  s   "€r   r   rà  ”  s?   ø€ ÷ ñ ÙðÙ$.ðÙ=EÁc½]ðÙVYðÙ^fÑgqÕ^rñr   c             ƒ  ó   "  € R# 5i)a  Deliver only the remainder of a partially delivered split payload. ``None`` (the default) means
this adapter cannot resume; ``_send_with_retry`` then returns the partial failure instead of
re-sending the whole payload. Override only where non-delivery of the remainder is CERTAIN.Nrt   )rë  rC  re   rß  r�   s   &&&$$r   r	  Ú(BasePlatformAdapter._resume_partial_send”  r  rØ  c          
      óH   <€ V ^8„  d   QhRS[ RS[ RS[S[ ,          RS[RS[/# rÞ  )r8   rf  rg  rI  )r   rä  s   "€r   r   rà  ›  s9   ø€ ÷ 2ñ 2Ùð2Ù),ð2Ù;CÁC½=ð2ÙTWð2Ù\fñ2r   c          
   ƒ  óš   "  € V P                  WP                  \        RVR,          R7      VR,          WR7      W4R7      G Rj  x€L
 #  L5i)z¤Last-resort send after a non-transient failure; platforms whose markup is not the
likely culprit override it (Photon drops rich links instead of adding the banner).z$gateway.notify.plain_fallback_prefix:Ni¬  N)r  rØ  ru  N)rã  rç  r   râ  s   &&&$$r   r	  Ú(BasePlatformAdapter._send_plain_fallback›  sZ   é € ð —Y‘YØ×%6Ñ%6ÜÐ8À'È%Å.ÔQÐSZÐ[`ÕSaØð &7ó &4ð ð	 ó 2÷ 2ð 	2ñ 2ùs   ‚AAÁA	ÁAc                ó<   <€ V ^8„  d   QhRS[ S[,          RS[RS[/# )r   Úexisting_textÚnew_textr   r"  )r   rä  s   "€r   r   rà  ¦  s&   ø€ ÷ 8ñ 8¡h©s¥mð 8¹sð 8Ásñ 8r   c                óÐ   € V '       g   V# VP                  4       V P                  R4       Uu. uF  q"P                  4       NK  	  up9   d   V # V  RV 2P                  4       # u upi )u¸   Merge a new caption into existing text unless an identical (stripped) caption already
exists â€” exact match per caption, not substring ("Meeting" isn't swallowed by "Meeting
agenda").r
  )r‹   r›  )r(	  r)	  r>  s   && r   r¯  Ú"BasePlatformAdapter._merge_caption¥  sa   € ÷
 ØˆOØ�>‰>Ó°=×3FÑ3FÀvÔ3NÓOÑ3N¨a§¡¦	Ñ3NÑOÔOØ Ð Ø�  X JÐ/×5Ñ5Ó7Ð7ùò  Ps   ­A#c                ó6   <€ V ^8„  d   QhRS[ S[S[3,          /# rj   )r|   r8   r  )r   rä  s   "€r   r   rà  °  s   ø€ ÷ 8ñ 8¡d©3Ñ0AÐ+AÕ&Bñ 8r   c                ó$   € \        V R \        4      # )r  )rÝ  r|   r™  s   &r   Ú_text_debounce_storeÚ(BasePlatformAdapter._text_debounce_store°  s   € Ü˜$Ð 0´$Ó7Ð7r   c                ó&   <€ V ^8„  d   QhRS[ RS[/# r?  r@  )r   rä  s   "€r   r   rà  ³  s   ø€ ÷ 	ñ 	±|ð 	Éñ 	r   c           	     óì  € \        V RR4      R8H  ;'       dŠ    VP                  \        P                  8H  ;'       de    \        VRR4      '       * ;'       dK    VP	                  4       '       * ;'       d.    \        VP                  ;'       g    RP                  4       4      pV'       dK   \        P                  RV P                  \        VRR	4      \        VP                  ;'       g    R4      4       V# )
z=Return True for normal text eligible for queue-mode debounce.rþ  rê  Úqueuer¡   Frn   zC[%s] Queue-text debounce candidate accepted: session=%s text_len=%drú  rU  )ro   r5  r{  r6  Ú
is_commandrµ   r   r‹   r   r«  rF  rÒ   )rë  r–   re   s   && r   Ú!_is_queue_text_debounce_candidateÚ5BasePlatformAdapter._is_queue_text_debounce_candidate³  sÛ   € ô �DÐ+¨[Ó9¸WÑD÷ Lð LØ×"Ñ"¤k×&6Ñ&6Ñ6÷Lð LÜ?FÀuÈjÐZ_Ó?`Ô;`÷Lð Là×$Ñ$Ó&Ô&÷Lð Lä+/°·±×1AÐ1A¸r×0HÑ0HÓ0JÓ+Kð 	÷ Ü�L‰LÐ^ØŸ™¤G¨E°=À#Ó$FÌÈEÏJÉJ×L\ÐL\ÐZ\ÓH]ô_àˆr   c                ó,   <€ V ^8„  d   QhRS[ RS[ RS[/# )r   r   r–   r   r@  )r   rä  s   "€r   r   rà  ¾  s(   ø€ ÷ Sñ S¹ð SÉ\ð SÑ^bñ Sr   c                óJ   € R R lpV! V4      pVRJ;'       d    WC! V4      8H  # )zDReturn True when two text debounce events came from the same sender.c                óX   € V ^8„  d   QhR\         R\        \        R3,          R,          /# )r   r)  r   .N)rz  r%  r8   )r   s   "r   r   ÚIBasePlatformAdapter._can_merge_text_debounce_events.<locals>.__annotate__Á  s'   € ÷ 
	ñ 
	¤ð 
	´%¼¸S¸µ/ÀDÕ2Hñ 
	r   c                 ó@  € \        V R R4      pVf   R# \        \        VRR4      4      p\        VRR4      ;'       g    \        VRR4      pV'       d   V\        V4      3# \        VRR4      R9   d,   \        VRR4      '       d   VR\        VP                  4      3# R# )	rŒ   Nrq   Úuser_id_altr  rƒ   r„   rC  >   r„   Úprivate)ro   rr   r8   rC  )r)  rŒ   rq   r¨  s   &   r   Ú	_identityÚFBasePlatformAdapter._can_merge_text_debounce_events.<locals>._identityÁ  s™   € Ü˜Y¨°$Ó7ˆFØŠ~ÙÜ%¤g¨f°jÀ$Ó&GÓHˆHÜ˜V ]°DÓ9×]Ð]¼WÀVÈYÐX\Ó=]ˆFßØ ¤# f£+Ð.Ð.Ü�v˜{¨DÓ1Ð5FÔFÌ7ÐSYÐ[dÐfj×KkÒKkØ  $¬¨F¯N©NÓ(;Ð<Ð<Ùr   Nrt   )rë  r   r–   r=	  Úexisting_senders   &&&  r   Ú_can_merge_text_debounce_eventsÚ3BasePlatformAdapter._can_merge_text_debounce_events¾  s0   € õ
	ñ $ HÓ-ˆØ dÐ*×RÐR¨À)ÈEÓBRÑ/RÐRr   c                ó&   <€ V ^8„  d   QhRS[ RS[/# rù  ©r8   r¨  )r   rä  s   "€r   r   rà  Ï  s   ø€ ÷ 5ñ 5±ð 5¹ñ 5r   c                ó  € V P                  4       P                  V4      pVf   R# \        VP                  V P                  ,           VP
                  V P                  ,           4      p\        RV\        P                  ! 4       ,
          4      # )z<Return bounded busy-text debounce delay for ``session_key``.r¬  )
r.	  r¥   rZ  r  r   r  r  r¯  r  r  )rë  rú  Ústater  s   &&  r   Ú_text_debounce_delayÚ(BasePlatformAdapter._text_debounce_delayÏ  sj   € à×)Ñ)Ó+×/Ñ/°Ó<ˆØŠ=ÙÜ�u—}‘} t×'GÑ'GÕGØ—~‘~¨×(HÑ(HÕHóJˆä�3˜¤4§>¢>Ó#3Õ3Ó4Ð4r   c                ó*   <€ V ^8„  d   QhRS[ RS[RR/# )r   rú  r–   r   N)r8   rz  )r   rä  s   "€r   r   rà  Ø  s(   ø€ ÷ Xñ X±cð XÁ,ð XÐSWñ Xr   c              ƒ  ó   "  € V P                  4       pVP                  V4      pVeÃ   V P                  VP                  V4      '       g¡   V P	                  V4      G Rj  x€L
  VP                  V4      pVes   V P                  VP                  V4      '       gQ   V P
                  P                  V4      pVe0   V P                  WR4      '       d   \        V P
                  WRR7       R# \        P                  ! 4       pVf   \        VRWfR7      pWCV&   MèVP                  '       d:   \        VP                  P                  VP                  4      VP                  n
        VP                  P                  V4       \        VRR4      pT;'       g    \        VRR4      pVe   \        V4      VP                  n        Ve7   \!        VP                  R4      '       d   \        V4      VP                  n        Wdn        VP'                  4        V P)                  V4      p	\*        P,                  ! V P/                  W4      4      Vn        R#  ELí5i)z@Buffer normal queue-mode busy text and schedule a bounded flush.NT©rž  )r–   r   r  r  r‡   rz   )r.	  r¥   r@	  r–   Ú_flush_text_debounce_nowrù  r»  r  r  r  r   r$  r°  ro   r8   r‡   r±  rz   r  r  rF	  r   rw  Ú_flush_text_debouncer   )
rë  rú  r–   rä  rE	  Úexisting_pendingr  Úlatest_message_idÚlatest_anchorr	  s
   &&&       r   Ú_queue_text_debounceÚ(BasePlatformAdapter._queue_text_debounceØ  sÐ  é € à×)Ñ)Ó+ˆØ—	‘	˜+Ó&ˆØÒ T×%IÑ%IÈ%Ï+É+ÐW\×%]Ò%]ð ×/Ñ/°Ó<×<Ð<Ø—I‘I˜kÓ*ˆEØÒ ¨×)MÑ)MÈeÏkÉkÐ[`×)aÒ)aØ#'×#9Ñ#9×#=Ñ#=¸kÓ#JÐ Ø#Ò/°D×4XÑ4XÐYi×4qÒ4qÜ/°×0FÑ0FÈÐgkÕlÙÜ�nŠnÓˆØŠ=Ü%¨E¸ÀsÔXˆEØ!&�+Òà�z�zˆzÜ#/°·±×0@Ñ0@À%Ç*Á*Ó#M�—‘Ô Ø�K‰K×-Ñ-¨eÔ4Ü '¨¨|¸TÓ BÐØ-×\Ð\´¸Ð@UÐW[Ó1\ˆMØ Ò,Ü),Ð->Ó)?�—‘Ô&ØÒ(¬W°U·[±[ÐBW×-XÒ-XÜ25°mÓ2D�—‘Ô/ØŒMØ×ÑÔØ×)Ñ)¨+Ó6ˆÜ×(Ò(¨×)BÑ)BÀ;Ó)VÓWˆŽ
ò1 =ùs-   ‚AIÁ
IÁIÁ:IÂBIÄ(A)IÆB:Ic                ó*   <€ V ^8„  d   QhRS[ RS[RR/# )r   rú  r	  r   NrC	  )r   rä  s   "€r   r   rà  ù  s"   ø€ ÷ "ñ "±cð "Á%ð "ÈDñ "r   c              ƒ  ó¸  "  €  \         P                  ! V4      G Rj  x€L
  V P                  V4      G Rj  x€L
   \         P                  ! 4       pT P                  4       P                  T4      pTe   TP                  TJ d
   RTn        R# R# R#  Ls L\  \         P                   dX     \         P                  ! 4       pT P                  4       P                  T4      pTe   TP                  TJ d
   RTn        R# R# R# i ; i  \         P                  ! 4       pT P                  4       P                  T4      pTe   TP                  TJ d	   RTn        i i i ; i5i)z2Timer task that flushes the debounced text buffer.N)r   r  rK	  r¶  r”  r.	  r¥   r   )rë  rú  r	  rÁ  rE	  s   &&&  r   rL	  Ú(BasePlatformAdapter._flush_text_debounceù  s)  é € ð		"Ü—-’- Ó&×&Ð&Ø×/Ñ/°Ó<×<Ñ<ô ×*Ò*Ó,ˆGØ×-Ñ-Ó/×3Ñ3°KÓ@ˆEØÒ  U§Z¡Z°7Ó%:Ø!�–
ñ &;Ñ ñ 'Ù<øÜ×%Ñ%ô 	Øä×*Ò*Ó,ˆGØ×-Ñ-Ó/×3Ñ3°KÓ@ˆEØÒ  U§Z¡Z°7Ó%:Ø!�–
ñ &;Ñ ð	ûô ×*Ò*Ó,ˆGØ×-Ñ-Ó/×3Ñ3°KÓ@ˆEØÒ  U§Z¡Z°7Ó%:Ø!�•
ð &;Ð üs\   ‚E„B �BžB ¶B·B ¼AEÂB ÂB ÂDÂ*D Â+AEÄ DÄD ÄAEÅEc                ó&   <€ V ^8„  d   QhRS[ RS[/# rù  r´   )r   rä  s   "€r   r   rà    s   ø€ ÷ ñ ¹#ð Á$ñ r   c              ƒ  ó   "  € V P                  4       pVP                  V4      pVf   R# VP                  \        P                  ! 4       R7       RVn        V P                  P                  V4      pVe$   V P                  WCP                  4      '       g   R# VP                  VR4       \        V P                  WP                  RR7       R# 5i)z@Force-flush one debounced busy-text burst into the pending slot.NF)r  TrJ	  )r.	  r¥   r  r   r”  r   rù  r@	  r–   rã  r»  )rë  rú  rä  rE	  r}  s   &&   r   rK	  Ú,BasePlatformAdapter._flush_text_debounce_now  s§   é € à×)Ñ)Ó+ˆØ—	‘	˜+Ó&ˆØŠ=ÙØ×Ñ¤'×"6Ò"6Ó"8ÐÔ9ØˆŒ
Ø×(Ñ(×,Ñ,¨[Ó9ˆØÒ t×'KÑ'KÈG×U`ÑU`×'aÒ'aÙØ�	‰	�+˜tÔ$Ü# D×$:Ñ$:¸KÏÉÐaeÕfÙùs   ‚CCc                ó$   <€ V ^8„  d   QhRS[ RR/# ©r   rú  r   Nrk   )r   rä  s   "€r   r   rà    s   ø€ ÷ .ñ .±#ð .¸$ñ .r   c                óŠ   € V P                  4       P                  VR4      pVe   VP                  4        ^ RIHp V! W4       R# )zACancel and drop pending text debounce state for control commands.N)Údiscard_busy_burst)r.	  rã  r  Úgateway.session_ingress_burstr[	  )rë  rú  rE	  r[	  s   &&  r   Ú_discard_text_debounceÚ*BasePlatformAdapter._discard_text_debounce  s:   € à×)Ñ)Ó+×/Ñ/°¸TÓBˆØÒØ×ÑÔ ÝDÙ˜4Ö-r   Úguardc                óN   <€ V ^8„  d   QhRS[ RS[S[P                  ,          RR/# )r   rú  r_	  r   N©r8   rf  r   rx  )r   rä  s   "€r   r   rà     s,   ø€ ÷ /ñ /±#ð /ÁÉ'Ï-É-ÕAXð /Ðdhñ /r   c               ót   € V P                   P                  V4      pVe
   Ve   W2Jd   R# V P                   V R# )z­Release the session guard; with ``guard`` given, only if the entry is still that exact
Event (an old task's unwind must not clear the guard a reset-like command swapped in).N)rø  r¥   )rë  rú  r_	  Úcurrent_guards   &&$ r   Ú_release_session_guardÚ*BasePlatformAdapter._release_session_guard   s;   € ð ×-Ñ-×1Ñ1°+Ó>ˆØÒ  UÒ%6¸=Ó;UÙØ×!Ñ! +Ò.r   c                ó&   <€ V ^8„  d   QhRS[ RS[/# rù  r´   )r   rä  s   "€r   r   rà  (  s   ø€ ÷ %ñ %±#ð %¹$ñ %r   c                ó‚   € \        V P                  P                  V4      RR4      p\        T;'       d    V! 4       4      # )z­True if the recorded owner task for ``session_key`` has exited. No owner task at all is
NOT stale (guards installed outside handle_message, as tests do, must not be healed).r  N)ro   rý  r¥   rµ   )rë  rú  r  s   && r   Ú_session_task_is_staleÚ*BasePlatformAdapter._session_task_is_stale(  s6   € ô �t×*Ñ*×.Ñ.¨{Ó;¸VÀTÓJˆÜ�D—O�O™T›VÓ$Ð$r   c                ó&   <€ V ^8„  d   QhRS[ RS[/# rù  r´   )r   rä  s   "€r   r   rà  .  s   ø€ ÷ ñ ±Cð ¹Dñ r   c                óœ  € WP                   9  g   V P                  V4      '       g   R# \        P                  RV P                  V4       V P                   P                  VR4       V P                  P                  VR4       V P                  P                  VR4       V P                  P                  VR4       V P                  V4       R# )z­Clear a stale session lock; True if healed. On-entry safety net: without it a split-brain
(guard held, nothing processing) traps the chat in "Interrupting..." until restart.FzB[%s] Healing stale session lock for %s (owner task is done/absent)NT)
rø  rh	  r   rX   rF  rã  rù  rú  rý  r]	  ©rë  rú  s   &&r   Ú_heal_stale_session_lockÚ,BasePlatformAdapter._heal_stale_session_lock.  s¥   € ð ×3Ñ3Ô3¸4×;VÑ;VÐWb×;cÒ;cÙÜ�‰Ð[Ø—y‘y +ô	/à×Ñ×!Ñ! +¨tÔ4Ø×Ñ×"Ñ" ;°Ô5Ø×Ñ× Ñ  ¨dÔ3Ø×Ñ×Ñ ¨TÔ2Ø×#Ñ# KÔ0Ùr   Úinterrupt_eventc                óV   <€ V ^8„  d   QhRS[ RS[RS[S[P                  ,          RS[/# )r   r–   rú  ro	  r   )rz  r8   rf  r   rx  rµ   )r   rä  s   "€r   r   rà  <  s4   ø€ ÷ ñ ©|ð É#ð Ù3;¹G¿M¹MÕ3JðÙVZñr   c               ó8  € T;'       g    \         P                  ! 4       pW@P                  V&   \         P                  ! V P	                  W4      4      pV P                  W%4      '       g1   V P                  P                  VR4       V P                  W$R7       R# R# )z®Spawn a background processing task under the session guard; True on success. If
``create_task`` is stubbed with a non-Task sentinel (tests), the guard is rolled back
(False).N©r_	  FT)	r   rx  rø  rw  Ú_process_message_backgroundÚ_track_session_taskrý  rã  rd	  )rë  r–   rú  ro	  r_	  r   s   &&&$  r   Ú_start_session_processingÚ-BasePlatformAdapter._start_session_processing<  s~   € ð
  ×2Ð2¤7§=¢=£?ˆØ-2×Ñ˜kÑ*Ü×"Ò" 4×#CÑ#CÀEÓ#WÓXˆØ×'Ñ'¨×:Ò:Ø×Ñ×#Ñ# K°Ô6Ø×'Ñ'¨Ð'ÔAÙÙr   c                ó,   <€ V ^8„  d   QhRS[ RS[RS[/# )r   rú  r   r   r  )r   rä  s   "€r   r   rà  J  s"   ø€ ÷ ñ ©sð ¹#ð Á$ñ r   c                ó6  € W P                   V&    V P                  P                  V4       \	        TR4      '       dK   TP                  T P                  P                  4       TP                  T P                  P                  4       R#   \         d     R# i ; i)u¶   Record ``task`` as the session owner and track it for shutdown; False when
``create_task`` was stubbed with an unhashable sentinel (tests) â€” the owner entry is left
for the caller.Fr³  T)rý  r  r©  rž  r±  r³  r´  r  )rë  rú  r   s   &&&r   rt	  Ú'BasePlatformAdapter._track_session_taskJ  s†   € ð ,0×Ñ˜KÑ(ð	Ø×"Ñ"×&Ñ& tÔ,ô �4Ð,×-Ò-Ø×"Ñ" 4×#9Ñ#9×#AÑ#AÔBØ×"Ñ" 4×#AÑ#A×#IÑ#IÔJÙøô ô 	Úð	ús   �B	 Â	BÂBÚrelease_guardÚdiscard_pendingc                ó0   <€ V ^8„  d   QhRS[ RS[RS[RR/# )r   rú  rz	  r{	  r   Nr´   )r   rä  s   "€r   r   rà  X  s,   ø€ ÷ 5ñ 5¹3ð 5ÑRVð 5Ù9=ð5ØIMñ5r   c             ƒ  óF  "  € V P                   P                  VR4       V P                  P                  VR4      pVe˜   VP                  4       '       g‚   \        P                  RV P                  V4       V P                  P                  V4       VP                  4         \        P                  ! \        P                  ! V4      RR7      G Rj  x€L
  V'       d.   V P"                  P                  VR4       V P%                  V4       V'       d   V P'                  V4       R# R#  LV  \        P                   d     Lk\         d%    \        P                  RT P                  T4        L˜\          d'    \        P                  RT P                  TRR7        LÇi ; i5i)	z¹Cancel in-flight processing for one session. ``release_guard=False`` keeps the guard so
reset-like commands finish atomically; the await is bounded (5s) so a wedged finally can't
stall.Nz0[%s] Cancelling active processing for session %srh   rÅ  zt[%s] Cancelled task for %s did not exit within 5s; unblocking dispatch and letting the task unwind in the backgroundz3[%s] Session cancellation raised while unwinding %sTr   )rú  rã  rý  r  r   r«  rF  r  r©  r  r   rÍ  rµ  r¶  rÏ  rX   r[   rù  r]	  rd	  )rë  rú  rz	  r{	  r   s   &&$$ r   Úcancel_session_processingÚ-BasePlatformAdapter.cancel_session_processingX  sG  é € ð
 	×Ñ× Ñ  ¨dÔ3Ø×"Ñ"×&Ñ& {°DÓ9ˆØÒ D§I¡I§K¢KÜ�L‰LÐKÈTÏYÉYÐXcÔdØ×*Ñ*×.Ñ.¨tÔ4Ø�K‰KŒMð
9Ü×&Ò&¤w§~¢~°dÓ';ÀSÔI×IÐI÷ Ø×"Ñ"×&Ñ& {°DÔ9Ø×'Ñ'¨Ô4ßØ×'Ñ'¨Ö4ñ ñ JøÜ×)Ñ)ô ÙÜô 7Ü—‘ð  cà#Ÿy™y¨+ö7ô ô 9Ü—‘ÐRÐTX×T]ÑT]Ø(°4ð ö 9ð9üss   ‚AF!ÁAF!Â"/D* ÃD(ÃD* ÃF!Ã4F!ÄF!Ä(D* Ä*FÄ?F!ÅFÅ
"FÅ,F!Å.FÅ7$FÆF!ÆFÆF!c                ó>   <€ V ^8„  d   QhRS[ RS[P                  RR/# )r   rú  Úcommand_guardr   N©r8   r   rx  )r   rä  s   "€r   r   rà  t  s.   ø€ ÷ Gñ GÙðGÙ/6¯}©}ðGØAEñGr   c              ƒ  óÎ   "  € V P                  V4      G Rj  x€L
  V P                  P                  VR4      pV P                  WR7       Ve   V P	                  W14       R# R#  LK5i)z…Tail of /stop, /new, /reset: release the command-scoped guard, then
spawn a fresh processing task for any follow-up queued meanwhile.Nrr	  )rK	  rù  rã  rd	  ru	  )rë  rú  r�	  Úpending_events   &&& r   Ú$_drain_pending_after_session_commandÚ8BasePlatformAdapter._drain_pending_after_session_commandt  sb   é € ð ×+Ñ+¨KÓ8×8Ð8Ø×.Ñ.×2Ñ2°;ÀÓEˆØ×#Ñ# KÐ#ÔEØÒ$Ø×*Ñ*¨=ÖFñ %ñ 	9ùs   ‚A%—A#˜AA%c                ó0   <€ V ^8„  d   QhRS[ RS[RS[RR/# )r   r–   rú  Úcmdr   Nre  )r   rä  s   "€r   r   rà  ~  s2   ø€ ÷ Tñ T¹Lð TÑWZð TÑadð TÐimñ Tr   c              ƒ  ó@  "  € \         P                  RV P                  W24       V P                  P	                  V4      p\
        P                  ! 4       pWPP                  V&    V P                  WR7      G Rj  x€L
  V P                  VRRR7      G Rj  x€L
  T P                  Y%4      G Rj  x€L
  R#  L; L!  \         dW    T P                  P	                  T4      TJ d6   Y P                  9   d   Te   Y@P                  T&   h T P                  Y%R7       h i ; i Ln5i)z¼Dispatch a reset-like bypass command (/stop, /new, /reset): keep a guard installed while
the runner handles it (follow-ups stay queued), cancel the old task AFTER the response,
drain once.ú8[%s] Command '/%s' bypassing active-session guard for %s)ræ  NF)rz	  r{	  rr	  )r   r«  rF  rø  r¥   r   rx  rì  r~	  r[   rý  rd	  r…	  )rë  r–   rú  rˆ	  rc	  r�	  s   &&&&  r   Ú _dispatch_active_session_commandÚ4BasePlatformAdapter._dispatch_active_session_command~  s  é € ô 	�‰ÐOÐQU×QZÑQZÐ\_ÔmØ×-Ñ-×1Ñ1°+Ó>ˆÜŸš›ˆØ-:×Ñ˜kÑ*ð	ð ×-Ñ-¨eÐ-ÓA×AÐAØ×0Ñ0°ÈEÐchÐ0Ói×iÐið ×7Ñ7¸ÓS×SÒSñ BÙiøÜô 	à×$Ñ$×(Ñ(¨Ó5¸ÓFØ×"5Ñ"5Ô5¸-Ò:SØ9F×)Ñ)¨+Ñ6ð ð ×/Ñ/°Ð/ÔQØð	úñ 	TùsO   ‚A DÁ#B8 Á8B4Á9B8 ÂB6ÂB8 ÂDÂ-DÂ.DÂ4B8 Â6B8 Â8A!DÄDc                ó$   <€ V ^8„  d   QhRS[ RR/# r/  r0  )r   rä  s   "€r   r   rà  •  s   ø€ ÷ *Uñ *U©,ð *U¸4ñ *Ur   c              ƒ  ó4  "  € RVn         V P                  '       g=   \        V RR4      '       g(   RV n        \        P                  RV P                  4       R# VP                  '       d   \        V4       V P                  V4      '       d   R# \        VP                  ;'       g    / P                  R4      ;'       g    R4      P                  4       pV'       g}   \        V RR4      en   VP                  P                  \         P"                  8X  dE   VP                  P$                  R	8X  d*   \&        P(                  ! V P*                  V4      G Rj  x€L
  V P-                  V4      pV'       d   W28w  d   \        P/                  R
W#4       R# ^ RIHp V! WV4      G Rj  x€L
 pW0P4                  9   d   V P7                  V4       W0P4                  9   g	   V'       d   V P9                  W4      G Rj  x€L
  R# V P;                  W4      Vn         R#  L¾ Lr L"5i)z‹Process an incoming message; returns quickly by spawning a background
task so new messages (and interrupts) can arrive while an agent runs.Frì  Tz¦[%s] Dropping inbound message: no gateway message handler is installed on this adapter. The adapter is connected and can send, but every inbound message is discarded.NÚgateway_session_keyrn   rï  r„   z@Dropping internally routed event: expected session=%s derived=%s)Ú
burst_gate)Ú_gateway_acceptedrë  ro   rì  r   r   rF  Úallow_gateway_controlr8  rE  r8   r�   r¥   r‹   rŒ   rq   rl  ÚTELEGRAMrƒ   r   r   r
  ri  rX   r\	  r�	  rø  rm	  Ú_handle_message_while_activeru	  )rë  r–   Úexpected_session_keyrú  r�	  Úbehind_bursts   &&    r   rŠ  Ú"BasePlatformAdapter.handle_message•  s¯  é € ð #(ˆÔØ×$×$Ð$ô ˜4Ð!=¸u×EÒEØ26�Ô/Ü—‘ðHð —I‘Iô	ñ à×&×&Ð&Ü,¨UÔ3à× Ñ  ×'Ò'ÙÜ" E§N¡N×$8Ð$8°b×#=Ñ#=Ð>SÓ#T×#ZÐ#ZÐXZÓ[×aÑaÓcÐ÷ %¬°Ð7KÈTÓ)RÒ)^Ø—L‘L×)Ñ)¬X×->Ñ->Ô>À5Ç<Á<×CYÑCYÐ]aÔCaÜ×#Ò# D×$>Ñ$>ÀÓF×FÐFØ×-Ñ-¨eÓ4ˆß KÔ$GÜ�N‰NÐ]Ø/ô>áÝ<Ù'¨°[ÓA×Aˆà×/Ñ/Ô/Ø×)Ñ)¨+Ô6Ø×/Ñ/Ô/·<Ø×3Ñ3°EÓG×GÐGÙà"&×"@Ñ"@ÀÓ"TˆÖñ Gñ Bñ
 Hùsa   ‚A'HÁ*!HÂHÂ&HÂ?HÃA7HÅHÅHÅ10HÆ!HÆ"<HÇHÇ3HÇ4HÈHÈHc                ó&   <€ V ^8„  d   QhRS[ RS[/# r?  r@  )r   rä  s   "€r   r   rà  Á  s   ø€ ÷ bñ b±ð bÁñ br   c                óˆ   € \        V P                  RR4      p\        VRR4      RJ;'       d    VP                  4       '       * # )zPTrue when a non-command input belongs to the shared runtime's session authority.Ú__self__NÚsession_authority)ro   rë  Úget_command)rë  r–   r8  s   && r   Ú_shared_runtime_owns_inputÚ.BasePlatformAdapter._shared_runtime_owns_inputÁ  s?   € ä˜×.Ñ.°
¸DÓAˆÜ�vÐ2°DÓ9ÀÐE×aÐaÈe×N_ÑN_ÓNaÔJaÐar   c                ó,   <€ V ^8„  d   QhRS[ RS[RS[/# )r   r–   rú  r   )rz  r8   r$  )r   rä  s   "€r   r   rà  Æ  s#   ø€ ÷ ñ ©lð Éð ÑQUñ r   c                ó$  € V .p\        V RR4      pVeG    VP                  VP                  4      pVe'   WPJd"   W%P                  9  d   VP                  V4       V#   \         d(    Rp\        P                  RT P                  RR7        L]i ; i)z¯Adapters whose pending slot may hold *event* after busy admission: this one, plus the
runner's current delivery adapter for its source when that replacement has no live guard.r6  Nz;[%s] Delivery-adapter lookup failed during pending recoveryTr   )	ro   rö  rŒ   r[   r   r«  rF  rø  r­  )rë  r–   rú  Úownersr8  Údelivery_adapters   &&&   r   Ú_pending_recovery_ownersÚ,BasePlatformAdapter._pending_recovery_ownersÆ  sš   € ð �ˆÜ˜Ð/°Ó6ˆØÒð7Ø#)×#?Ñ#?ÀÇÁÓ#MÐ ð
 !Ò,Ð1AÓ1MØ#×+LÑ+LÔLØ—‘Ð.Ô/Øˆøô ô 7Ø#'Ð Ü—‘ÐZØ!ŸY™Y°ð ö 7ð7ús   –A Á/BÂBc                ó*   <€ V ^8„  d   QhRS[ RS[RR/# ©r   r–   rú  r   Nre  )r   rä  s   "€r   r   rà  ×  s)   ø€ ÷ e+ñ e+¹ð e+ÑSVð e+Ð[_ñ e+r   c           	   ƒ  ó~  "  € V P                  V4      '       d   ^ RIHp V! WV4      G Rj  x€L
  R# T P                  VP                  4       VP                  4       p^ RIHpHp V! V4      '       d‚    V'       d<   V! V4      '       d.   V P                  V4       V P                  WV4      G Rj  x€L
  R# \        P                  RV P                  WB4       V P                  V4      G Rj  x€L
   R# V'       gt   VP"                  '       db    ^ RIHp VP)                  VRR	7      RJp	V	'       d>   \        P                  RV P                  V4        V P                  V4      G Rj  x€L
  R# V P*                  e›    V P+                  W4      G Rj  x€L
 p
W P.                  9  dg   RpV P1                  W4       F+  pVP3                  V4      pVf   K  VP5                  W²4        M	  Vf!   V
'       g   V P5                  W4      Vn        R# V
'       d   R# VP6                  '       d   W P8                  9   d   R# VP:                  \<        P>                  8X  dA   \        P                  RV P                  V4       \A        V P8                  W!4       RVn        R# V PC                  V4      '       dG   \        P                  RV P                  W PD                  4       V PG                  W!4      G Rj  x€L
  R# \        P                  RV P                  V4       \A        V P8                  W!VP:                  \<        PH                  8H  R7       RVn        R#  EL) EL§ ELn  \         d/   p\        P!                  RT P                  YGRR7        Rp?R# Rp?ii ; i  \         d    R
p	 ELi ; i ELE  \         d/   p\        P!                  RT P                  TRR7        Rp?R# Rp?ii ; i ELZ  \         d=   p\        P!                  RT P                  TRR7       TP,                  RJ p
 Rp?ELšRp?ii ; i ELI5i)z‰Route a message that arrived while ``session_key`` is busy: bypass
commands / clarify replies dispatch inline, everything else is queued.)Údispatch_busy_burstN)Úis_interrupt_then_dispatchÚshould_bypass_active_sessionrŠ	  z&[%s] Command '/%s' dispatch failed: %sTr   )Úclarify_gateway)Úinclude_choice_promptsFz5[%s] Routing message to clarify text-intercept for %sz/[%s] Clarify text-intercept dispatch failed: %sz$[%s] Busy-session handler failed: %sz=[%s] Queuing photo follow-up for session %s without interruptun   [%s] New text message while session %s is active â€” debouncing follow-up (busy_text_mode=queue, window=%.2fs)uq   [%s] New message while session %s is active â€” queuing follow-up (no interrupt, will cascade after current turn)rJ	  )%r�	  r\	  r¨	  r<  rŒ   rœ	  Úhermes_cli.commandsr©	  rª	  r]	  r‹	  r   r«  rF  rì  r[   r   r’	  Útoolsr«	  Úget_pending_for_sessionr  r‘	  rø  r£	  Úget_pending_messageru	  r¡   rù  r5  r{  r­  r»  r4	  r   rP	  r6  )rë  r–   rú  r¨	  rˆ	  r©	  rª	  r  Ú_clarify_modÚ_has_text_clarifyÚhandledÚorphanr-  s   &&&          r   r”	  Ú0BasePlatformAdapter._handle_message_while_active×  s½  é € ð ×*Ñ*¨5×1Ò1ÝIÙ% d°;Ó?×?Ð?Ùð 	×Ñ˜5Ÿ<™<Ô(Ø×ÑÓ!ˆßbÙ'¨×,Ò,ð
içÑ5°c×:Ò:Ø×/Ñ/°Ô<Ø×?Ñ?ÀÐTWÓX×XÐXñ ô —L‘LÐ![Ø!%§¡¨Cô>à×5Ñ5°eÓ<×<Ñ<ñ ÷ �u×2×2Ð2ð*ÝAØ$0×$HÑ$HØ¸ð %Ió %>ØEIð%JÐ!÷ !Ü—‘ÐTÐVZ×V_ÑV_ÐalÔmðqØ×5Ñ5°eÓ<×<Ð<ñ Ø×%Ñ%Ò1ð:Ø $× :Ñ :¸5Ó N×N�ð ×"7Ñ"7Ô7ð �Ø!×:Ñ:¸5ÖN�EØ"×6Ñ6°{ÓC�FØÔ)Ø×7Ñ7¸ÔLÙñ	 Oð
 ’>¯'Ø.2×.LÑ.LÈUÓ.`�EÔ+ÙßÙð �>�>ˆ>˜k×-CÑ-CÔCÙà×Ñ¤×!2Ñ!2Ô2Ü�L‰LÐXÐZ^×ZcÑZcÐepÔqÜ'¨×(>Ñ(>ÀÔSØ&*ˆEÔ#ÙØ×1Ñ1°%×8Ò8Ü�L‰Lð UØVZ×V_ÑV_Ø$×&FÑ&FôHð ×+Ñ+¨KÓ?×?Ò?ä�L‰Lð KØLPÏIÉIÐWbôdä'¨×(>Ñ(>ÀØ38×3EÑ3EÌ×IYÑIYÑ3Yõ[à&*ˆEÖ#ò @ò" Yò =øÜô iÜ—‘ÐEÀtÇyÁyÐRUÐcg�×hÐhÙûðiûô ô *Ø$)Ó!ð*úò
 =øÜ ô qÜ—L‘LÐ!RÐTX×T]ÑT]Ð_`Ðko�L×pÐpÙûðqúò
 OøÜô :Ü—‘ÐCÀTÇYÁYÐPQÐ\`�Ôað  ×1Ñ1°TÐ9–ûð	:úòR @ùsJ  ‚*P=¬M­AP=Á5M Á=M Â&M Â1MÂ2M Â6P=Â85M Ã-MÃ.M Ã2
P=Ã=P=ÄN Ä+P=Ä3!P=ÅN1 Å)N.Å*N1 Å.P=Å?O0 ÆO-ÆO0 Æ8P=Ç P=Ç6P=ÈP=È*BP=Ê2?P=Ë1P:Ë2A$P=ÍM ÍM ÍNÍ)#NÎP=ÎNÎP=ÎN+Î'P=Î*N+Î+P=Î.N1 Î1O*Î<#O%ÏP=Ï%O*Ï*P=Ï-O0 Ï0P7Ï;1P2Ð,P=Ð2P7Ð7P=c                ó    <€ V ^8„  d   QhRS[ /# rj   r§  )r   rä  s   "€r   r   rà  >  s   ø€ ÷ 8ñ 8¡%ñ 8r   c                ó€   € V P                   pV'       g   R# Vw  r#\        P                  ! VR,          VR,          4      # )z«Random human-like pacing delay (s) from this adapter's ``human_delay`` config range
(ms), installed per profile by the runner (``_wire_adapter_handlers``); ``None`` = off.r¬  g     @�@)r  r	  r	  )rë  ÚboundsrÚ   rÛ   s   &   r   Ú_get_human_delayÚ$BasePlatformAdapter._get_human_delay>  s5   € ð ×+Ñ+ˆßÙØ‰ˆÜ�~Š~˜b 6�k¨2°­;Ó7Ð7r   c                ó\   <€ V ^8„  d   QhRS[ RS[S[S[ ,          S[S[ ,          3,          /# )r   r(  r   )r8   r%  r$  rf  )r   rä  s   "€r   r   rà  G  s0   ø€ ÷ %ñ %±sð %¹uÁTÉ#ÅYÑPXÑY\ÕP]ÐE]Õ?^ñ %r   c              ƒ  ó®  "  € . pRp ^ RI HpHp V! 4       '       dô   ^ RIpV P	                  V4      pV'       g   \        R4      h\        V P                  4      pTP                  \        P                  ! WGVR7      G Rj  x€L
 4      pVP                  RR4      '       dp   VP                  R4      ;'       g    VP                  R4      .p	V	 U
u. uF8  qª'       g   K  \        V
4      P                  4       '       g   K-  \        V
4      NK:  	  pp
W#3#  L’u up
i   \         d.   p\         P#                  R	T P$                  T4        Rp?Y#3# Rp?ii ; i5i)
zÁSynthesize auto-TTS audio -> ``(existing_paths, requested_path)``; empty/None on failure
(logged, never raised). Path built platform-aware HERE: HERMES_SESSION_PLATFORM is cleared
post-handler.N)Útext_to_speech_toolÚcheck_tts_requirementsz!Empty text after markdown cleanup)r   r4   rK  TrE  r)  z[%s] Auto-TTS failed: %s)rÅ   r½	  r¾	  rê  ró  rñ   rÎ   rq   rë  r   r   r¥   rb  Úexistsr8   r[   r   rX   rF  )rë  r(  ÚpathsÚrequested_pathr½	  r¾	  rï  Úspeech_textÚtts_dataÚraw_tts_pathsr6   Útts_errs   &&          r   Ú_synthesize_auto_ttsÚ(BasePlatformAdapter._synthesize_auto_ttsG  s&  é € ð ˆØˆð	KßRÙ%×'Ò'Û$Ø"×3Ñ3°LÓA�ß"Ü$Ð%HÓIÐIÜ!;¸D¿M¹MÓ!J�Ø Ÿ;™;¬W×->Ò->Ø'À~ô.W÷ (Wó X�à—<‘< 	¨4×0Ò0Ø$,§L¡L°Ó$>×$]Ð$]À8Ç<Á<ÐP[ÓC\ÐB]�MÙ3@Óa±=¨4ÃDœYÌTÐRVËZ×M^ÑM^×M`œYœS žY±=�EÐað Ð$Ð$ñ(Wùò bøÜô 	KÜ�N‰NÐ5°t·y±yÀ'×JÐJØÐ$Ð$ûð	Küsp   ‚Eˆ1D ºAD Â DÂD Â!D Â9D Ã	DÃDÃ?DÄD ÄEÄD ÄD ÄEÄ%!EÅEÅEÅEc                óR   <€ V ^8„  d   QhRS[ RS[RS[P                  RS[RS[RS[/# )r   r–   rú  ro	  r(  r)  r   )rz  r8   r   rx  r$  rµ   )r   rä  s   "€r   r   rà  ^  sI   ø€ ÷ ^ñ ^¡\ð ^Áð ^ÑV]×VcÑVcð ^Ù&)ð^Ù8<ð^ÙAEñ^r   c                ó4  € \        VRR4      p\        V P                  VP                  P                  4      ;'       dW    VP
                  \        P                  8H  ;'       d2    T;'       d(    V'       * ;'       d    V P                  W&VR7      '       * 4      # )z‡Auto-TTS on voice input (voice-first), gated by /voice or voice.auto_tts;
skipped when streaming TTS already delivered audio this turn.Ú_hermes_run_generationNr•   )	ro   rµ   rv  rŒ   rC  r5  r{  ÚVOICEr!  )rë  r–   rú  ro	  r(  r)  r˜  s   &&&&&& r   Ú_wants_auto_ttsÚ#BasePlatformAdapter._wants_auto_tts^  s�   € ô ˜_Ð.FÈÓMˆ
ÜØ×*Ñ*¨5¯<©<×+?Ñ+?Ó@÷ ]ð ]Ø×"Ñ"¤k×&7Ñ&7Ñ7÷]ð ]Ø<H÷]ð ]ØQ\Ì_÷]ð ]à×6Ñ6°{ÐV[Ð6Ó\Ô\ó^ð 	^r   c                óZ   <€ V ^8„  d   QhRS[ RS[RS[RS[RS[S[S[3,          RS[RS[/# )r   r–   r(  Útts_pathr­  r�   Úrecord_deliveryr   )rz  r8   rµ   r|   rg  rh  )r   rä  s   "€r   r   rà  h  sV   ø€ ÷ Gñ GÙ!ðGÙ14ðGÙ@CðGÙLPðGá‘s™C�x•.ðGá3;ðGá@DñGr   c              ƒ  ó@  "  € RpV'       d8   V P                   \        P                  8X  d   V'       d   VR,          V8X  d   TpV P                  VP                  P
                  W7VR7      G Rj  x€L
 pV! V4       \        T;'       d    \        VRR4      4      #  L,5i)u¢   Play one synthesized TTS file. Returns True when the ORIGINAL reply text rode
along as a Telegram caption (first file, â‰¤1024 chars) so the text send is skipped.N:Ni   N)rC  rÍ   r   r�   rK  F)rq   rl  r“	  r÷  rŒ   rC  rµ   ro   )	rë  r–   r(  rÏ	  r­  r�   rÐ	  r   Ú
tts_results	   &&&&&&&  r   Ú_play_tts_fileÚ"BasePlatformAdapter._play_tts_fileh  s‹   é € ð
 ˆß�T—]‘]¤h×&7Ñ&7Ô7¿LÈ\ÐZ_ÕM`ÐdpÔMpØ"ˆGØŸ=™=Ø—L‘L×(Ñ(°XÐYað )ó c÷ cˆ
á˜
Ô#Ü�G×EÐE¤¨
°I¸uÓ EÓFÐFñcùs   ‚1B´;BÁ/BÁ0BÂ
Bc                óL   <€ V ^8„  d   QhRS[ RS[RS[RRRS[RS[S[,          /# )r   r–   rú  r(  r¢	  r¦  Úis_ephemeral_responser   )rz  r8   rµ   rf  )r   rä  s   "€r   r   rà  u  sC   ø€ ÷  ñ  Ù!ð Ù03ð ÙCFð à/ð áHLð áQYÑZ]ÕQ^ñ r   c              ƒ  ó:  "  € V'       gY   \        VP                  ;'       g    R4      P                  4       P                  RV P                  ;'       g    R34      '       d   R#  ^ RIHpHpHpH	p	 \        P                  ! V4      G Rj  x€L
 '       g   R# VP                  p
\        VRR4      pVf   \        VRR4      pT! T\        T;'       g    R4      V4      p\        P                  ! WœV\        \        V
P                  RV
P                  4      4      V
P                  \        V
R	R4      V\        VR
R4      R7      G Rj  x€L
  \        P                  ! WŒ4      G Rj  x€L
  V#  Là L& L
  \          d    \"        P%                  RRR7        R# i ; i5i)z¼Ledger the final response BEFORE the send so a crash before platform ACK redelivers on
next boot; best-effort, skips slash-command and ephemeral replies. Returns the obligation id
or None.rn   ré  Ú!N)Úcompute_obligation_idÚledger_enabledÚmark_attemptingÚrecord_obligationÚledger_message_idr‡   rm   r~   r	  )Úobligation_idrú  rq   rC  r~   r  Úadapter_profilezdelivery ledger record failedTr   )r8   r   r}  r=  Útyped_command_prefixÚgateway.delivery_ledgerrÙ	  rÚ	  rÛ	  rÜ	  r   r   rŒ   ro   rq   rC  r[   r   r«  )rë  r–   rú  r(  r¢	  rÖ	  rÙ	  rÚ	  rÛ	  rÜ	  rŒ   Ú
_ledger_idrÞ	  s   &&&&&&       r   Ú_record_delivery_obligationÚ/BasePlatformAdapter._record_delivery_obligationu  so  é € ÷ !¤C¨¯
©
×(8Ð(8°bÓ$9×$@Ñ$@Ó$B×$MÑ$MØ�$×+Ñ+×2Ð2¨sÐ3÷%5ò %5áð	÷[ó [ä ×*Ò*¨>Ó:×:Ö:ÙØ—\‘\ˆFô ! Ð(;¸TÓBˆJØÒ!Ü$ U¨L¸"Ó=�
Ù1ØœS ×!1Ð!1¨rÓ2°LóBˆMä×#Ò#Ø!ÈKÜœW V§_¡_°g¸v¿¹ÓOÓPØŸ™´'¸&À+ÈtÓ2TØ$Ü 'Ð(8Ð:JÈDÓ QôS÷ Sð Sô ×#Ò# OÓC×CÐCØ Ð ñ# ;ñSñ Døäô 	Ü�L‰LÐ8À4ˆLÔHÚð	üsƒ   ‚ F£1FÁFÁ#FÁ&%E2 ÂE,Â	E2 ÂFÂ:E2 ÃA4E2 ÅE.ÅE2 Å%E0Å&E2 Å+FÅ,E2 Å.E2 Å0E2 Å2"FÆFÆFÆFc          
      ó4   <€ V ^8„  d   QhRS[ RS[RS[RRRR/# )r   rÞ	  re   r–   r¢	  r¦  r   N)r8   rg  rz  )r   rä  s   "€r   r   rà  —  s<   ø€ ÷ Iñ IÙ ðIÙ*-ðIÙ6BðIà/ðIà48ñIr   c              ƒ  óL  "  €  ^ RI Hp ^ RIHpHpHp \        VRR4      '       d!   \        P                  ! Wq4      G Rj  x€L
  R# \        \        VRR4      ;'       g    R4      p	\        P                  ! W�V	4      G Rj  x€L
  V! V	4      '       d€   \        V P                  RR4      p
V P                  VP                  4      pW´JdG   \        V
4      '       d4   V
! VP                  P                  \        VR	R4      R
7      G Rj  x€L
  R# R# R# V! V	4      fV   \        V P                  RR4      p\        V4      '       d,   V! VP                  P                  \        VR	R4      R
7       R# R# R#  EL4 Lõ Lp  \         d    \         P#                  RRR7        R# i ; i5i)a¦  Mark the ledger row delivered/failed (best-effort). On ``send_path_degraded`` with a
replacement adapter live, trigger another redelivery sweep (the watcher's may have run
before this failure landed; atomic claiming keeps it idempotent). On any other rejection arm
the runner's timed redelivery, so the reply goes out once the flood penalty or the retry
backoff has passed instead of waiting for the next restart (#91653).)Úclassify_dead_error)Úis_reconnect_onlyÚmark_deliveredÚmark_failedrK  FNr   rn   Ú*_redeliver_failed_obligations_for_platformr	  )r‰   Ú_schedule_flood_redeliveryzdelivery ledger update failedTr   )Úgateway.dead_targetsrç	  rá	  rè	  ré	  rê	  ro   r   r   r8   r6  rø  rŒ   r;  rq   r[   r   r«  )rë  rÞ	  re   r–   r¢	  rç	  rè	  ré	  rê	  r   Ú	redeliverÚliveÚschedules   &&&&&        r   Ú_finalize_delivery_obligationÚ1BasePlatformAdapter._finalize_delivery_obligation—  s~  é € ð	IÝ@ß^Ñ^Ü�v˜y¨%×0Ò0Ü×'Ò'¨ÓF×FÐFÙÜœ ¨°Ó4×:Ð:¸Ó;ˆEÜ×#Ò# KÀÓF×FÐFÙ  ×'Ò'Ü#Ø×'Ñ'Ð)UÐW[ó]�	à×3Ñ3°E·L±LÓA�ØÓ/´H¸Y×4GÒ4GÙ# E§L¡L×$9Ñ$9Ü,3Ð4DÐFVÐX\Ó,]ô_÷ _ò _ñ 5HÑ/ñ % UÓ+Ò3Ü" 4×#6Ñ#6Ð8TÐVZÓ[�Ü˜H×%Ò%Ù˜UŸ\™\×2Ñ2Ü%,Ð-=Ð?OÐQUÓ%V÷Xñ &ñ 4ò Gñ Gñ_øô ô 	IÜ�L‰LÐ8À4ˆL×Hð	Iüs„   ‚F$„<E; Á E4ÁE; ÁF$ÁE; Á !E; ÂE7ÂE; ÂA4E; ÄE9Ä	E; ÄF$ÄAE; Å.F$Å4E; Å7E; Å9E; Å;"F!ÆF$Æ F!Æ!F$c                ó^   <€ V ^8„  d   QhRS[ RS[RS[RS[RS[RS[S[S[3,          RS[RR	/# )
r   r–   r)  r*  r+  r—  r�   rÐ	  r   N)rz  r$  rµ   r¨  r|   r8   rg  rh  )r   rä  s   "€r   r   rà  ¶  sd   ø€ ÷ 3_ñ 3_Ù!ð3_Ù04ð3_ÙCGð3_á$(ð3_á7<ð3_áHLÉSÑRUÈXÍð3_ñ "ð3_ð '+ñ3_r   c          
   ƒ  óž  a aaa"  € ^ RI Hp R V3R llp	V U
Uu. uF!  w  r«V'       d   K  V	! V
4      '       g   K  V
NK#  	  pp
pYÃ U
u. uF  q©! V
4      '       g   K  V
NK  	  up
,          pV'       d8   S P                  Y U
u. uF  p
RV! V
4       2R3NK  	  up
SVV4      G Rj  x€L
  VP                  P                  oR VVV 3R llpV U
Uu. uF!  w  r®V'       g   V	! V
4      '       d   K  W®R	3NK#  	  pp
pV'       d+   \
        P                  R
S P                  \        V4      4       Yó U
u. uF  q©! V
4      '       d   K  V
RR3NK  	  up
,          pV FF  w  pppV^ 8”  d   \        P                  ! V4      G Rj  x€L
   T! V! VVVR7      G Rj  x€L
 4       KH  	  R# u upp
i u up
i u up
i  ELu upp
i u up
i  LB L.  \         dy   pT! \        R\        T4      R7      4       T'       d(   \
        P                  RS P                  T4        Rp?KÄ  \
        P                  RS P                  TT4        Rp?Kì  Rp?ii ; i5i)uX  Deliver MEDIA-tag files and detected local files by type: images batched via
``send_multiple_images`` unless ``[[as_document]]``; otherwise audio â†’ send_voice (MEDIA
tags only, never bare local files), video â†’ send_video, else send_document. Every failure is
reported. Each send feeds ``record_delivery`` so media-only turns report SUCCESS.)Úquotec                ó0   € V ^8„  d   QhR\         R\        /# rS  r´   )r   s   "r   r   ÚDBasePlatformAdapter._deliver_media_attachments.<locals>.__annotate__À  s   € ÷ 	_ñ 	_œCð 	_¤Dñ 	_r   c                 óv   <€ \        V 4      P                  P                  4       \        9   ;'       d    S'       * # r¼  )rb  r>   rp   Ú_IMAGE_EXTS)r6   r+  s   &€r   Ú	_as_imageÚABasePlatformAdapter._deliver_media_attachments.<locals>._as_imageÀ  s-   ø€ Ü˜“:×$Ñ$×*Ñ*Ó,´Ñ;×^Ð^ÐD^Ô@^Ð^r   rš  rn   Nc                óH   € V ^8„  d   QhR\         R\        R\        R\        /# )r   r6   r³   Ú	media_tagr   rì  )r   s   "r   r   r÷	  Ê  s(   € ÷ 	ñ 	¤#ð 	´Dð 	ÄTð 	Ìjñ 	r   c             “  ó�  <"  € \        V 4      P                  P                  4       pV'       d<   \        SP                  W1R7      '       d   SP                  SV SVR7      G Rj  x€L
 pMnV\        9   dH   V'       d#   \        P                  RSP                  VS4       SP                  SV SR7      G Rj  x€L
 pMSP                  SV SR7      G Rj  x€L
 pVP                  '       gS   \        P                  RSP                  V'       d   RMR	W4P                  4       SP                  SWSR
7      G Rj  x€L
  V#  LÙ L‰ Ln L5i)zSMEDIA-tag files (``media_tag``) may route to send_voice; bare local files never
do.r0  )rC  rÍ   r�   r³   Nz([%s] Sending video attachment (%s) to %s)rC  r$  r�   )rC  r)  r�   z[%s] Failed to send %s (%s): %sr¡  z
local file)r³   r�   )rb  r>   rp   rº   rq   rË  r1  r   rÊ  rF  r&  r+  rK  rX   r   r5  )r6   r³   rý	  r²   re   rC  r�   rë  s   &$$  €€€r   Ú	_send_oneÚABasePlatformAdapter._deliver_media_attachments.<locals>._send_oneÊ  s  øé € ô �t“*×#Ñ#×)Ñ)Ó+ˆCßÔ7¸¿¹Às×^Ó^Ø#Ÿ™°wÈ4ÐZbÐmu˜Óv×v‘ØœÔ#ßÜ—K‘KÐ JÈDÏIÉIÐWZÐ\cÔdØ#Ÿ™°wÈ4ÐZb˜Óc×c‘à#×1Ñ1¸'ÈTÐ\dÐ1Óe×e�Ø—>—>�>Ü—‘Ð@À$Ç)Á)ß*3™w¸ÀsÏLÉLôZà×9Ñ9¸'À4ÐemÐ9Ón×nÐnØˆMñ wñ dáeñ oùsZ   ƒA!EÁ$D>Á%EÁ=9EÂ6E Â7EÃEÃEÃ*"EÄ*EÄ7EÄ8EÅ EÅEÅETz0[%s] Delivering %d non-image MEDIA attachment(s)F)r³   rý	  rï  z[%s] Error sending media: %sz$[%s] Error sending local file %s: %s)Úurllib.parserõ	  Ú_send_image_batchrŒ   rC  r   rÊ  rF  rÒ   r   r  r[   rI  r8   rX   r   )rë  r–   r)  r*  r+  r—  r�   rÐ	  Ú_quoterú	  rm  r³   Ú_image_pathsrÿ	  Úvr2	  r6   rý	  ÚerrrC  s   f&&&d$d$           @r   Ú_deliver_media_attachmentsÚ.BasePlatformAdapter._deliver_media_attachments¶  só  ûé € õ 	1÷	_ð 	_á-8ÔZ©[™k˜aÄœÉYÐWXÏ\Ÿ˜©[ˆÑZØ KÓ@¡K˜q°9¸Q·<Ÿ˜¡KÑ@Õ@ˆßØ×(Ñ(Ø¸\ÓJ¹\¸˜7¡6¨!£9 +Ð.°Ó3¹\ÑJÈHÐVaØó!÷ !ð !ð —,‘,×&Ñ&ˆ÷	ò 	ñ" +6ÔO©+¡$ !¿Á)ÈAÇ,”�!˜“©+ˆÑOßÜ�K‰KÐJÈDÏIÉIÔWZÐ[`ÓWaÔbØ¨[ÓM©[¨À	È!ÇÔ#�1�e˜UÓ#©[ÑMÕMˆÛ).Ñ%ˆD�(˜IØ˜QŒÜ—m’m KÓ0×0Ð0ð_Ù¡i°¸xÐS\Ô&]× ]Ö^ó	 */ùó; [ùÚ@ùò Kò!ùó, Pùò Nñ 1á ]øÜô _Ù¤
°5ÄÀCÃÔ IÔJßÜ—N‘NÐ#AÀ4Ç9Á9Èc×RÒRä—L‘LÐ!GÈÏÉÐTXÐZ]×^Ò^ûð_üsÉ   †I›F%¬F%¼F%ÁIÁ	F+ÁF+Á#IÁ4IÂF0
ÂIÂ&F5Â'*IÃF8Ã0F8Ã89IÄ1F>Å	F>Å2IÆ GÆIÆGÆG
ÆGÆIÆ8IÇGÇI
ÇAIÈIÈ"IÈ?IÉI
É
Ic                óR   <€ V ^8„  d   QhRS[ RS[RS[S[S[3,          RS[RS[RR/# )r   r–   rT  r�   r—  rÐ	  r   N)rz  r$  r|   r8   rg  r¨  rh  )r   rä  s   "€r   r   rà  ë  sE   ø€ ÷  ñ  Ù!ð Ù+/ð Ù;?ÁÁSÀ½>ð ÙX]ð á!ð à&*ñ r   c           	   ƒ  ó4  "  €  V P                  VP                  P                  W#VR7      G Rj  x€L
 pT! T4       R#  L  \         dK   p\        P                  RT P                  TRR7       T! \        R\        T4      R7      4        Rp?R# Rp?ii ; i5i)zÁBatch-send images; a failure is logged (never raised) so other attachments still go.
The batch result feeds ``record_delivery`` so media-only turns report their real
outcome instead of FAILURE.)rC  rT  r�   r—  Nz[%s] Error batching images: %sTr   Frï  )	r¬  rŒ   rC  r[   r   rX   rF  rI  r8   )rë  r–   rT  r�   r—  rÐ	  re   Ú	batch_errs   &&&&&&  r   r
  Ú%BasePlatformAdapter._send_image_batchë  s‡   é € ð	Ø×4Ñ4ØŸ™×,Ñ,°VÐ\gð 5ó i÷ iˆFñ 	˜Öñiøäô 	Ü�N‰NÐ;¸T¿Y¹YÈ	Ð\`ˆNÔaÙœJ¨u¼CÀ	»NÔKÔLÝûð	üs;   ‚B„+A  ¯>°A  ´
B¾A  Á BÁ?BÂ
BÂBÂBrÖ	  c                óh   <€ V ^8„  d   QhRS[ RS[RS[RS[S[S[3,          RS[S[,          RS[RR/# )	r   r–   rú  r(  r�   rß  rÖ	  r   z&tuple[SendResult, BasePlatformAdapter])rz  r8   r|   rg  rf  rµ   )r   rä  s   "€r   r   rà  ú  sW   ø€ ÷ (ñ (Ù!ð(Ù03ð(ÙCFð(ÙRVÑWZÑ\_ÐW_ÕR`ð(á™3•-ð(á8<ð(ð 
2ñ(r   c             ƒ  ó   "  € V P                  VP                  4      p\        P                  RVP                  \        V4      VP                  P                  4       V P                  WW7V4      G Rj  x€L
 pVe   V P                  V4      G Rj  x€L
  VP                  VP                  P                  W5VR7      G Rj  x€L
 p	\        WqP                  P                  V	4       Ve   V P                  W‰W4      G Rj  x€L
  W—3#  L’ Lw LI L5i)u?  The delivery-ledger bracket every final text goes through, on the CURRENT transport
(a reconnect may have replaced this adapter): record the obligation before the send,
send with retry, finalize from the result â€” so a refused final (flood control, a dead
transport) leaves a ledger row the boot sweep / runtime redelivery can act on. ``event``
supplies the source and the ledger identity (``ledger_message_id`` or ``message_id``).
Returns the result with the adapter that sent it: that adapter owns ``result.message_id``
(an ephemeral delete must go to the same transport).z&[%s] Sending response (%d chars) to %sNru  )rø  rŒ   r   rÊ  rF  rÒ   rC  rã	  Ú_release_turn_markerré  r  rñ	  )
rë  r–   rú  r(  r�   rß  rÖ	  r¢	  rÞ	  re   s
   &&&&&$$   r   Úsend_final_ledgeredÚ'BasePlatformAdapter.send_final_ledgeredú  s   é € ð  ×7Ñ7¸¿¹ÓEÐÜ�‰Ð<Ð>N×>SÑ>SÜ˜Ó% u§|¡|×';Ñ';ô	=à"×>Ñ>Ø Ð@UóW÷ WˆàÒ$Ø×+Ñ+¨EÓ2×2Ð2Ø'×8Ñ8Ø—L‘L×(Ñ(°,Ð\dð 9ó f÷ fˆäÐ)¯<©<×+?Ñ+?ÀÔHØÒ$Ø×4Ñ4°]ÈEÓd×dÐdØÐ'Ð'ñWñ 3ñfñ eùsH   ‚A1DÁ3DÁ4DÂDÂ/DÃ D
Ã=DÃ>DÃ?DÄDÄ
DÄDc                ó$   <€ V ^8„  d   QhRS[ RR/# r/  r0  )r   rä  s   "€r   r   rà    s   ø€ ÷ Jñ J±ð JÀñ Jr   c              ƒ  ó  "  € \        VRR4      '       dE   \        VRR4      '       d2   V P                  e$   V P                  P                  V4      G Rj  x€L
  \        VR\        P                  ! 4       4      P                  4        R#  L45i)zÈClear the crash marker handed to this delivery lifecycle only once the final reply is ledgered or
nothing more is owed (no kill leaves a persisted reply with neither), then wake the drain. Idempotent.Ú_turn_marker_handoffFÚ_gateway_active_turn_tokenNÚ_gateway_marker_released)ro   r6  Ú_clear_durable_active_turnr   rx  r&  rh  s   &&r   r
  Ú(BasePlatformAdapter._release_turn_marker  so   é € ô �EÐ1°5×9Ò9¼gÀeÐMiÐko×>pÒ>pØ×'Ñ'Ò3Ø×%Ñ%×@Ñ@ÀÓG×GÐGÜ�Ð1´7·=²=³?ÓC×GÑGÖIñ Hùs   ‚ABÁB
Á5Bc                ó^   <€ V ^8„  d   QhRS[ RS[RS[RS[S[S[3,          RS[RS[RS[RR	/# )
r   r–   rú  r(  r�   rÖ	  Úephemeral_ttlrÐ	  r   N)rz  r8   r|   rg  rµ   r9   rh  )r   rä  s   "€r   r   rà    sc   ø€ ÷ 	pñ 	pÙ!ð	pÙ03ð	pÙCFð	pÙRVÑWZÑ\_ÐW_ÕR`ð	pá#ð	pá47ð	páJRð	pàW[ñ	pr   c           	   ƒ  óJ  "  € V P                  WW4\        V4      VR7      G Rj  x€L
 w  r‰V! V4       V'       de   V^ 8”  d\   VP                  '       dH   VP                  '       d4   V	P	                  VP
                  P                  VP                  V4       R# R# R# R# R#  L|5i)zSNormal-lane final: the ledger bracket plus the message-id owner's ephemeral delete.)rß  rÖ	  N)r
  r”   rK  r‡   r  rŒ   rC  )
rë  r–   rú  r(  r�   rÖ	  r
  rÐ	  re   r¢	  s
   &&&&&&&&  r   Ú_send_final_textÚ$BasePlatformAdapter._send_final_text  s•   é € ð *.×)AÑ)AØ Ü,¨UÓ3ÐK`ð *Bó *b÷ $bÑ ˆñ 	˜Ôß˜]¨QÔ.°6·>·>°>Àf×FW×FWÐFWØ×7Ñ7¸¿¹×8LÑ8LÈf×N_ÑN_ÐanÖoñ GX±>Ñ.‰=ñ	$bùs   ‚"B#¤B!¥.B#ÁB#Á&<B#c                ó<   <€ V ^8„  d   QhRS[ RS[RS[S[,          /# )r   r–   r  r   )rz  r\  rf  r|   )r   rä  s   "€r   r   rà  &  s)   ø€ ÷  ñ  ©lð  ¹}ð  ÑQYÑZ^ÕQ_ñ  r   c           
   ƒ  óÜ  "  € Rp \        V4      p\        V4      '       d   \        V4      R,          M
\        R4      pV P                  VP                  4      ;_uu_ 4        \        V4      '       d   RMeV P                  \        R\        V4      P                  VR7      \        R4      VP                  P                  VP                  P                  VR7      pRRR4       Xf   V# V P                  VP                  P                  WSR7      G Rj  x€L
  V#   + '       g   i     LG; i L  \         d/   p\        P                  R	T P                  TR
R7        Rp?T# Rp?ii ; i5i)z˜Tell the user a turn failed rather than leaving radio silence (last resort:
a failing notice is logged, never raised). Returns the thread metadata used.N:Ni,  Nz$gateway.notify.turn_error_no_detailsz"gateway.notify.turn_error_detailed)Ú
error_typeÚerror_detailzgateway.notify.turn_error)rÕ  rC  r�   rk  z2[%s] Failed to send error notification to user: %sTr   )r—   r8   r   rò  rŒ   r}  rç  rA  rÎ  rq   rC  rã  r[   r   r   rF  )rë  r–   r  Ú_thread_metadatar!
  r  r4  s   &&&    r   Ú_notify_turn_errorÚ&BasePlatformAdapter._notify_turn_error&  s;  é € ð  Ðð	lÜ9¸%Ó@ÐÜ+.¨q¯6ª6œ3˜q›6 $ž<´qÐ9_Ó7`ˆLð ×+Ñ+¨E¯L©L×9Õ9Ü"7¸×">Ò">™$ÀD×DUÑDUÜÐ:ÄtÈAÃw×GWÑGWÐfrÔsÜÐ1Ó2Ø%*§\¡\×%:Ñ%:ÀEÇLÁL×DXÑDXÐcsð EVó Eu�÷ :ð
 ŠØ'Ð'Ø—)‘) E§L¡L×$8Ñ$8À'�)Óe×eÐeð  Ð÷ :×9úñ føÜô 	lÜ�L‰LØDÀdÇiÁiÐQ[Ðfjð ÷ lð làÐûð	lüs`   ‚E,†AD0 Á"A:DÃD0 Ã)E,Ã**D0 ÄD.ÄD0 ÄE,ÄD+	Ä&	D0 Ä0E)Ä;#E$ÅE,Å$E)Å)E,c                óR   <€ V ^8„  d   QhRS[ RS[RS[S[S[3,          RS[RS[RR/# )r   r–   Ú	extractedr�   Úanything_sentrÐ	  r   N)rz  r&  r|   r8   rg  rµ   rh  )r   rä  s   "€r   r   rà  <  sL   ø€ ÷ Kñ K±ð KÑI[ð KÙ-1±#±s°(­^ðKÙOSðKá4<ðKàAEñKr   c          
   ƒ  óŒ  "  € V P                  4       pVP                  VP                  VP                  r˜pV'       dF   \        P                  RV P                  \        V4      4       V P                  WW6V4      G Rj  x€L
  V P                  WV	VP                  WcVR7      G Rj  x€L
  V'       gŒ   V'       g‚   V	'       gx   V'       gn   VP                  P                  4       '       dL   \        P                  RV P                  \        VP                  4      VP                  P                  4       R# R# R# R# R# R#  LÁ L›5i)zàSend extracted image URLs, MEDIA files and bare local files (human-paced),
then fail loudly if a non-empty response produced nothing deliverable. Attachment
results feed ``record_delivery`` so the turn outcome reflects them.z1[%s] Extracted %d image(s) to send as attachmentsN)r+  r—  r�   rÐ	  z¡[%s] response_delivery_dropped: non-empty response (%d chars) produced no delivered message or attachment for %s (empty after extract, recovery yielded nothing).)r¹	  rT  r)  r*  r   rÊ  rF  rÒ   r
  r
  r+  r,  r‹   r   rŒ   rC  )
rë  r–   r&
  r�   r'
  rÐ	  r—  rT  r)  r*  s
   &&&&$$    r   Ú_deliver_attachmentsÚ(BasePlatformAdapter._deliver_attachments<  s  é € ð ×+Ñ+Ó-ˆØ+4×+;Ñ+;¸Y×=RÑ=RÐT]×TiÑTi˜[ˆßÜ�K‰KÐKÈTÏYÉYÔX[Ð\bÓXcÔdØ×(Ñ(¨¸ÈÓ_×_Ð_Ø×-Ñ-Ø Ø'0×'KÑ'KØ#Èð .ó Y÷ 	Yð 	Y÷ §¯;¿+È9×K`ÑK`×KfÑKf×KhÒKhÜ�L‰Lð SàTX×T]ÑT]Ü˜Y×2Ñ2Ó3°U·\±\×5IÑ5IöKñ Li¹+©;¡‘ñ `ñ	YùsC   ‚A<EÁ>E Á?'EÂ&EÂ'EÂ3EÂ;EÃEÃEÃ+AEÅEc          	      óz   <€ V ^8„  d   QhRS[ RS[P                  RS[S[,          RS[S[P
                  ,          /# )r   r–   ro	  r�   r   )rz  r   rx  rf  r|   r   )r   rä  s   "€r   r   rà  Q  sB   ø€ ÷ 
Vñ 
V©<ð 
VÉ'Ï-É-ð 
VÙ(0±­ð
VÙ;CÁGÇLÁLÕ;Qñ
Vr   c                ó6  € \        V P                  RR4      '       d   \        VRR4      '       d   R# RV/pV P                  V P                  RRRR7      '       d   W$R&   \        P
                  ! V P                  ! VP                  P                  3/ VB 4      # )	z¡Spawn the typing-refresh task, or None when ``typing_indicator=False``.
``stop_event`` is passed only when the (possibly overridden) ``_keep_typing`` accepts it.Útyping_indicatorTÚ_heartbeat_session_idNr�   rw  Fr“  )ro   rè  r�  r�  r   rw  rŒ   rC  )rë  r–   ro	  r�   rª  s   &&&& r   Ú_start_typing_refreshÚ)BasePlatformAdapter._start_typing_refreshQ  s‰   € ô
 �t—{‘{Ð$6¸×=Ò=ÄÈÐPgÐim×AnÒAnÙØ",¨hÐ!7ˆØ×Ñ˜t×0Ñ0°,ÀuÐVZÐ×[Ò[Ø#2�<Ñ Ü×"Ò" 4×#4Ò#4°U·\±\×5IÑ5IÑ#TÈVÑ#TÓUÐUr   c          
      ó8   <€ V ^8„  d   QhRS[ RS[RS[ RS[RS[/# )r   r‘  r–   rú  rÖ	  r   )r8   rz  rµ   r&  )r   rä  s   "€r   r   rà  ]  s:   ø€ ÷ 0iñ 0i¹ð 0iÁLð 0iÑ_bð 0iÙBFð0iÙK]ñ0ir   c          
   ƒ  óÒ  "  € RV9   pTpV P                  VP                  4      ;_uu_ 4        V P                  V4      w  rqV P                  WsR7      pV P	                  V4      w  r‰\        V	4      P                  4       p	V'       d5   \        P                  RV P                  \        V4      \        V4      4       . p
V'       g&   V P                  V	4      w  r©V P                  W£R7      p
RRR4       X
'       d   V P                  V4      G Rj  x€L
 MRpV'       df   V
 Uu. uF  qÌV9   g   K  VNK  	  ppV'       dE   \        P                  RV P                  \        V4      V4       V
 Uu. uF  qÌV9  g   K  VNK  	  p
pV
'       d+   \        P                  RV P                  \        V
4      4       X	'       g{   X'       gs   V
'       gk   X'       gc   \        V4      P                  4       pV'       dB   \        P                  RV P                  \        V4      VP                  P                  4       Tp	\!        V	XXW¥VR7      #   + '       g   i     ELe; i ELLu upi u upi 5i)	uq  Split a handler response into deliverable text + attachments. Order matters: MEDIA tags â†’
image URLs â†’ residual directives â†’ bare local paths (skipped for ephemeral notices so config
paths stay text; unknown-extension MEDIA tags survive for the bare-path detector). History
dedup is bare-path only, off-loop, fail-open. An emptied non-empty response is recovered.r�  rK  z<[%s] extract_images found %d image(s) in response (%d chars)NzQ[%s] Suppressing %d bare local file path(s) already delivered in this session: %sz5[%s] extract_local_files found %d file(s) in responsez›[%s] response_delivery_recovered: extract pipeline reduced a non-empty response (%d chars) to empty with no attachment; delivering recovered original to %s)r(  rT  r)  r*  r+  r,  )rò  rŒ   r`  r?  rÇ  Ú_strip_media_directivesr‹   r   rÊ  rF  rÒ   rs  rG  rÐ  rX   rC  r&  )rë  r‘  r–   rú  rÖ	  Úforce_documentr,  r)  rT  r(  r*  rŸ  rm  Ú
suppressedÚ
_recovereds   &&&&$          r   Ú_extract_response_contentÚ-BasePlatformAdapter._extract_response_content]  s  é € ð +¨hÑ6ˆØˆð ×'Ñ'¨¯©×5Õ5Ø$(×$6Ñ$6°xÓ$@Ñ!ˆKØ×:Ñ:¸;Ð:Ó`ˆKØ#'×#6Ñ#6°xÓ#@Ñ ˆFô 3°<Ó@×FÑFÓHˆLßÜ—‘ÐZÐ\`×\eÑ\eÔgjÐkqÓgrÔtwð  yAó  uBô  CØˆKß(Ø,0×,DÑ,DÀ\Ó,RÑ)�Ø"×>Ñ>¸{Ð>Ód�÷ 6÷ "ð ×FÑFÀ{ÓS×SÐSØ'+ð 	çÙ%0ÓA¡[ ¸±LŸ!˜!¡[ˆJÐAßÜ—‘ð /Ø04·	±	¼3¸z»?ÈJôXá*5ÓJ©+ QÀ'Ñ9IŸq˜q©+�ÐJßÜ�K‰KÐOÐQU×QZÑQZÔ\_Ð`kÓ\lÔm÷ §¯+¿Ü0°Ó:×@Ñ@ÓBˆJßÜ—‘ð  TàUY×U^ÑU^Ü" ;Ó/°·±×1EÑ1EôGð  *�Ü!Ø%¨fÀ+Ø#Ð\gôið 	i÷G 6×5Ð5úò Tùò Bùò Kùs„   ‚+I'­BIÃ%IÃ*I'Ã:I'ÄIÄI'ÄI'Ä!IÄ.IÄ49I'Å-I"Å:I"Æ 	I'Æ
1I'Æ<I'ÇI'ÇI'ÇA2I'ÉI	É
I'É
I'c                ó>   <€ V ^8„  d   QhRS[ RS[P                  RR/# ©r   rú  ro	  r   Nr‚	  )r   rä  s   "€r   r   rà  �  s/   ø€ ÷ 
jñ 
j¹cð 
jÑT[×TaÑTað 
jÐfjñ 
jr   c              ƒ  óž  "  € V P                  V\        VRR4      R7      p\        V4      '       d„   \        P                  ! \
        P                  \        4      ;_uu_ 4        V! 4       p\        P                  ! V4      '       d%   \
        P                  ! V\        R7      G Rj  x€L
  RRR4       R# R#  L  + '       g   i     R# ; i5i)uæ   Run the one-shot post-delivery callback (bounded, errors swallowed). The generation is
read HERE â€” stamped on the interrupt event DURING the handler await; an earlier snapshot
would let stale runs fire a fresher run's callbacks.rÊ	  N)r˜  rÅ  )r¯  ro   r;  r\   r]   r   rÏ  r[   r‡  r¦  rÍ  Ú'_POST_DELIVERY_CALLBACK_TIMEOUT_SECONDS)rë  rú  ro	  Ú_post_cbÚ_post_results   &&&  r   Ú_fire_post_delivery_callbackÚ0BasePlatformAdapter._fire_post_delivery_callback�  s    é € ð ×2Ñ2Ø¤G¨OÐ=UÐW[Ó$\ð 3ó ^ˆä�H×ÒÜ×$Ò$¤W×%9Ñ%9¼9×EÕEÙ'›z�Ü×&Ò& |×4Ò4Ü!×*Ò*¨<ÔAhÔi×iÐi÷ FÑEñ ñ j÷ F×EÐEüs1   ‚A!CÁ#AB9Â&B7Â'B9Â+CÂ7B9Â9C
	Ã	Cc                ó>   <€ V ^8„  d   QhRS[ RS[P                  RR/# r:
  r‚	  )r   rä  s   "€r   r   rà  ›  s,   ø€ ÷ Nñ N±ð NÁgÇmÁmð NÐX\ñ Nr   c                ó®  € V P                   P                  VR4      p\        P                  ! 4       pVeh   V P                  P                  V4      pVe   WTJd   W0P                   V&   R# \        P                  RV P                  4       V P                  W14       R# Ve5   V P                  P                  V4      VJ d   V P                  W4       R# R# R# )a  End-of-task guard/ownership reconciliation. A late ``_pending_messages`` arrival must not
drop: re-queue it if another task already owns the session (drain handoff), else spawn the
drain task and leave it the guard. Nothing pending: release the guard only if we still own
it.NuH   [%s] Late-arrival pending message during cleanup â€” spawning drain task)rù  rã  r   r”  rý  r¥   r   r«  rF  Ú_spawn_drain_taskÚ_cleanup_finished_session_task)rë  rú  ro	  Úlate_pendingr”  Úexisting_tasks   &&&   r   Ú_finish_session_taskÚ(BasePlatformAdapter._finish_session_task›  s¾   € ð
 ×-Ñ-×1Ñ1°+¸tÓDˆÜ×+Ò+Ó-ˆØÒ#Ø ×/Ñ/×3Ñ3°KÓ@ˆMØÒ(¨]Ó-Nð 7C×&Ñ& {Ó3ä—‘Ø^Ø—I‘Iôð ×&Ñ& |ÖAØÒ%¨$×*=Ñ*=×*AÑ*AÀ+Ó*NÐR^Ó*^Ø×/Ñ/°ÖMñ +_Ñ%r   c                ó*   <€ V ^8„  d   QhRS[ RS[RR/# r¦	  re  )r   rä  s   "€r   r   rà  ³  s.   ø€ ÷ {Dñ {D±|ð {DÑRUð {DÐZ^ñ {Dr   c           
   ƒ  óB  aa"  € R;ooVV3R lpV P                   P                  V4      ;'       g    \        P                  ! 4       pW@P                   V&   \	        V4      pV P                  WV4      p V P                  RV4      G Rj  x€L
  V P                  RJVn        V P                  V4      G Rj  x€L
 pV P                  VP                  4      ;_uu_ 4        \        V4      '       d   RpRRR4       \        V\        4      pV P                  V4      w  ryV'       dJ   VP!                  4       '       d4   W P"                  9   d$   \$        P'                  RV P(                  V4       RpV'       g8   \$        P+                  RV P(                  VP                  P,                  4       EMV P/                  WqW(R7      G Rj  x€L
 p
V
P0                  V
P2                  rË\5        V4      p. RrþV P7                  WWKV4      '       d   V P9                  V4      G Rj  x€L
 w  rïRp\;        V4       Fo  w  pp TV P=                  WVV^ 8H  VV4      G Rj  x€L
 ,          p\>        P@                  ! \B        4      ;_uu_ 4        \D        PF                  ! V4       RRR4       Kq  	  V'       gF   VeB   \>        P@                  ! \B        4      ;_uu_ 4        \D        PF                  ! V4       RRR4       V'       gG   V
PH                  '       g5   V
P2                  '       g#   V
PJ                  '       g   V'       g	   V'       d&   V PM                  VP                  P,                  4       V'       d%   V'       g   V PO                  WW½W‰V4      G Rj  x€L
  T PQ                  YTS;'       g    TVR7      G Rj  x€L
  V PS                  V4      G Rj  x€L
  S'       d   SM\U        V4      '       * pV PV                  PY                  V P[                  V\]        VR	R4      VR
7      ;'       g    R4       T P                  RTV'       d   \^        P`                  M\^        Pb                  4      G Rj  x€L
  V Pe                  V4      G Rj  x€L
  W P"                  9   Ed„   V P"                  V,          pV Pg                  VVV4      pV'       g   V P"                  Pi                  V4       \$        P+                  RV P(                  4       V Pk                  V4       V Pm                  VP                  P,                  WeR7      G Rj  x€L
  V Po                  VVVR7        V PS                  V4      G Rj  x€L
  RVn        V Pm                  VP                  P,                  WeR7      G Rj  x€L
  V Pq                  W$4      G Rj  x€L
  V Pm                  VP                  P,                  RV^R7      G Rj  x€L
  V Pe                  V4      G Rj  x€L
  V Ps                  W$4       R#  T PS                  T4      G Rj  x€L
  RTn        T Pm                  TP                  P,                  YeR7      G Rj  x€L
  T Pq                  Y$4      G Rj  x€L
  T Pm                  TP                  P,                  RT^R7      G Rj  x€L
  T Pe                  T4      G Rj  x€L
  T Ps                  Y$4       R#  ELS EL*  + '       g   i     ELú; i EL4 ELà EL¬  + '       g   i     EKä  ; i  \>        P@                  ! \B        4      ;_uu_ 4        \D        PF                  ! T4       RRR4       i   + '       g   i     i ; i; i  + '       g   i     EL‘; i ELú ELÖ ELÀ EL& EL ELY EL. ELû ELå EL· EL¡  \        Pt                   dg    \        Pv                  ! 4       T Px                  9   pT P                  RTT'       d   \^        Pz                  M\^        Pb                  4      G Rj  x€L 
  h \|         d›   pT P                  RT\^        Pb                  4      G Rj  x€L 
  \$        P                  RT P(                  TRR7       T P�                  TT4      G Rj  x€L 
 ;'       g    Tp\        T\‚        \„        34      '       d   h  Rp?EL¤Rp?ii ; i EL˜ ELe ELO EL! EL  T PS                  T4      G Rj  x€L 
  RTn        T Pm                  TP                  P,                  YeR7      G Rj  x€L 
  T Pq                  Y$4      G Rj  x€L 
  T Pm                  TP                  P,                  RT^R7      G Rj  x€L 
  T Pe                  T4      G Rj  x€L 
  T Ps                  Y$4       i ; i5i)z4Background task that actually processes the message.Fc                 óX   <€ V e%   RoS;'       g    \        \        V RR4      4      oR # R # )NTrK  F)rµ   ro   )re   Údelivery_attemptedÚdelivery_succeededs   &€€r   Ú_record_deliveryÚIBasePlatformAdapter._process_message_background.<locals>._record_delivery·  s2   ø€ àÒ!Ø%)Ð"Ø%7×%bÐ%b¼4ÄÈÐPYÐ[`Ó@aÓ;bÒ"ñ "r   r³  Nz:[%s] Suppressing stale response for interrupted session %sz0[%s] Handler returned empty/None response for %s)rÖ	  )r'
  rÐ	  rÊ	  r•   rn   rÀ  z([%s] Processing queued follow-up messagerÃ  )r	  )r�   rƒ  z[%s] Error handling message: %sTr   )Crø  r¥   r   rx  r—   r/
  rÆ  r6  r
  rë  rò  rŒ   r}  r¤   rŒ  rä  r{  rù  r   rÊ  rF  r«  rC  r7
  r(  r)  rœ   rÌ	  rÆ	  rm  rÓ	  r\   r]   r^   rP   r¥  rT  r*  rŽ  r
  r)
  r
  rµ   r  r´  r  ro   r|  r½  r¾  rK	  Ú_requeue_backoff_delayrã  Ú_clear_session_guardr‡  rC
  r?
  rG
  r¶  r”  r  Ú	CANCELLEDr\  r   r#
  Ú
SystemExitÚKeyboardInterrupt)rë  r–   rú  rN
  ro	  r"
  r…  r‘  rÖ	  Ú_ephemeral_ttlr&
  r(  r)  Ú_final_thread_metadataÚ
_tts_pathsÚ_tts_requested_pathÚ_tts_caption_deliveredÚ
_tts_indexÚ	_tts_pathÚprocessing_okr„	  r	  Úexpectedr  rL
  rM
  s   &&&                     @@r   rs	  Ú/BasePlatformAdapter._process_message_background³  sB  ùé € à27Ð7ÐÐ/ö	cð ×/Ñ/×3Ñ3°KÓ@×SÐSÄGÇMÂMÃOˆØ-<×Ñ˜kÑ*Ü5°eÓ<ÐØ×0Ñ0°ÐIYÓZˆðm	DØ×+Ñ+Ð,AÀ5ÓI×IÐIØ)-×)<Ñ)<ÀDÐ)HˆEÔ&Ø!×2Ñ2°5Ó9×9ˆHð ×+Ñ+¨E¯L©L×9Õ9Ü(¨×/Ò/Ø#�H÷ :ô %/¨x¼Ó$HÐ!à'+×'=Ñ'=¸hÓ'GÑ$ˆHç˜O×2Ñ2×4Ò4¸×H^ÑH^Ô9^Ü—‘ÐXÐZ^×ZcÑZcØ'ô)à�ßÜ—‘ÐOÐQU×QZÑQZÐ\a×\hÑ\h×\pÑ\pÖqà"&×"@Ñ"@Ø [ð #Aó #_÷ _�	à,5×,BÑ,BÀI×DYÑDY˜kä)>Ð?OÓ)PÐ&Ø24°dÐ/Ø×'Ñ'Ø¨OÈ;÷Xò Xà<@×<UÑ<UÐVbÓ<c×6cÑ3�Jà).Ð&Ü-6°zÖ-BÑ)�J 	ð1Ø.¸×8KÑ8KØ!°¸JÈ!¹OÐMcØ,ó9.÷ 3.õ .Ð.ô (×0Ò0´×9Õ9ÜŸIšI iÔ0÷ :Ñ9ñ .C÷ "Ð&9Ò&EÜ#×,Ò,¬W×5Õ5ÜŸ	š	Ð"5Ô6÷ 6÷   9×#3×#3Ð#3°y×7L×7LÐ7LÐPY×Pe×PeÐPeß%×)?Ø×.Ñ.¨u¯|©|×/CÑ/CÔDß×(>Ø×/Ñ/Ø¨LØ-Ð?OóQ÷ Qð Qð ×/Ñ/ØÐ&<Ø"4×"NÐ"NÐ8NØ$4ð 0ó 6÷ 6ð 6ð ×+Ñ+¨EÓ2×2Ð2ß2DÑ.ÌdÐS[ËnÔJ\ˆMà×/Ñ/×7Ñ7¸×8TÑ8TØœW _Ð6NÐPTÓUØð 9Uó 9÷ 9#ð 9#à "ô$ð ×+Ñ+Ø(¨%ß-:Ô!×)Ò)Ô@Q×@YÑ@Yó[÷ [ð [ð
 ×/Ñ/°Ó<×<Ð<Ø×4Ñ4Õ4Ø $× 6Ñ 6°{Õ C�Ø×3Ñ3°KÀÐPUÓV�ßØ×*Ñ*×.Ñ.¨{Ô;Ü—‘ÐGÈÏÉÔSØ×)Ñ)¨+Ô6Ø×/Ñ/°·±×0DÑ0DÀkÐ/Óm×mÐmØ×&Ñ& }°kÈÐ&ÔOØð ×+Ñ+¨EÓ2×2Ð2Ø).ˆEÔ&ð ×+Ñ+¨E¯L©L×,@Ñ,@À+Ð+Ói×iÐiØ×3Ñ3°KÓQ×QÐQà×+Ñ+Ø—‘×$Ñ$ dÐ5EÐUVð ,ó X÷ Xð Xð ×/Ñ/°Ó<×<Ð<Ø×%Ñ% kÖCðG 5ð0 ×+Ñ+¨EÓ2×2Ð2Ø).ˆEÔ&ð ×+Ñ+¨E¯L©L×,@Ñ,@À+Ð+Ói×iÐiØ×3Ñ3°KÓQ×QÐQà×+Ñ+Ø—‘×$Ñ$ dÐ5EÐUVð ,ó X÷ Xð Xð ×/Ñ/°Ó<×<Ð<Ø×%Ñ% kÖCòY Jâ9÷ :×9Ð9úò_ò 7dò
3.÷ :×9Ñ9ûœZ×0Ò0´×9Õ9ÜŸIšI iÔ0÷ :×9×9Ð9ý÷ 6×5Ð5úòQò6ò 3ò[ò
 =ò nò" 3ò jÚQòXò =øô1 ×%Ñ%ô 	Ü×+Ò+Ó-°×1OÑ1OÑOˆHØ×+Ñ+Ø(¨%ß/7Ô!×+Ò+Ô=N×=VÑ=VóX÷ Xñ Xð Üô 	Ø×+Ñ+Ð,DÀeÔM^×MfÑMfÓg×gÑgÜ�L‰LÐ:¸D¿I¹IÀqÐSWˆLÔXØ&*×&=Ñ&=¸eÀQÓ&G× GÐ G×\Ð\ÐL\Ðä˜!œjÔ*;Ð<×=Ò=Øõ >ûð	úò 3ò jÚQòXò =øð ×+Ñ+¨EÓ2×2Ñ2Ø).ˆEÔ&ð ×+Ñ+¨E¯L©L×,@Ñ,@À+Ð+Ói×iÑiØ×3Ñ3°KÓQ×QÑQà×+Ñ+Ø—‘×$Ñ$ dÐ5EÐUVð ,ó X÷ Xñ Xð ×/Ñ/°Ó<×<Ñ<Ø×%Ñ% kÕCüs  „A/fÁ4^" Â	[Â
+^" Â5[Â6'^" Ã["Ã1A^" Ä::^" Å5A^" Ç[6ÇA^" È[9È^" È4\É[<É
\É"^" É=[?Ê^" Ê(&^" Ë]-Ë%^" Ë5^" Ì^" Ì^" Ì+^" Ì3^" Ì;,^" Í(^" Í0^" Î^Î^" Î"^" Î.^Î/^" Ï^Ï^" ÏA^" Ð!^" Ð='^" Ñ$^
Ñ%^" Ñ=^Ñ>A^" ÓA6^" Ô7^Ô8^" ÕfÕ%^Õ&5fÖ^ÖfÖ4^Ö50f×%^×&f×>^×?fØc ØfØ+cØ,5fÙ!cÙ"fÙ:c	Ù;0fÚ+cÚ,fÛcÛfÛ^" Û^" Û"[3	Û-
^" Û9^" Û<\Û?\Ü

^" Ü#]*Ü7]Ý	]*Ý]'Ý"]*Ý*^" Ý-]>	Ý8
^" Þ^" Þ^" Þ
^" Þ^" Þ^" ÞfÞfÞfÞfÞfÞ"Ac ß.'c à`àc à%c à&$b;á
aá=b;âbâ	b;â b;â5c â;c ã c ãfãfã	fãfãfãfã'c*ã(6fäd!äfä8d;ä91få*e-å+fæfæfæfrz  c                ó2   <€ V ^8„  d   QhRS[ RS[RS[RS[/# )r   rú  r„	  Údispatched_eventr   )r8   rz  r¨  )r   rä  s   "€r   r   rà  5  s+   ø€ ÷ ñ ±#ð Álð Ù1=ðÙBGñr   c                ó,  € VP                   VP                   8H  ;'       d7    \        VP                   4      ;'       g    VP                  VP                  8H  pV'       g   V P                  P	                  VR4       R# V P                  P                  V^ 4      pV^,           V P                  V&   V^ 8X  d   R# \        WPP                  V P                  RR7      pV^8X  d   \        P                  M\        P                  ! RV P                  W4       V# )a€  Delay before re-dispatching the queued follow-up.

Only the event this task just dispatched coming straight back backs off: the same
``message_id``, or for an id-less event the same ``timestamp`` (rewrite-hook
``dataclasses.replace`` copies keep both; a genuine new message gets a fresh timestamp).
The handler put it back because the session is busy elsewhere, and re-dispatching it at
once hot-loops for the whole busy window (#123229). Any other follow-up resets the counter
and runs immediately. The first bounce stays immediate (restart auto-resume relies on one
self-bounce), then back off exponentially to a cap. Defers, never drops.Nr¬  )rü  Ú	max_delayÚjitter_ratioz_[%s] Handler re-queued a pending event for %s again (session busy elsewhere); backing off %.2fs)r‡   rµ   Ú	timestamprú  rã  r¥   r	   Ú _REQUEUE_BACKOFF_INITIAL_SECONDSÚ_REQUEUE_BACKOFF_MAX_SECONDSr   rÊ  r«  rF  )rë  rú  r„	  r`
  ÚsameÚattemptsr	  s   &&&&   r   rP
  Ú*BasePlatformAdapter._requeue_backoff_delay5  sý   € ð ×(Ñ(Ð,<×,GÑ,GÑG÷ Oð OÜ˜-×2Ñ2Ó3÷ Nð NØ%×/Ñ/Ð3C×3MÑ3MÑMð 	÷ Ø× Ñ ×$Ñ$ [°$Ô7ÙØ×'Ñ'×+Ñ+¨K¸Ó;ˆØ,4°q­Lˆ×Ñ˜[Ñ)Ø�qŒ=ÙÜ  ×6[Ñ6[Ø+/×+LÑ+LÐ[^ô`ˆà  AœŒ�Š¬6¯<©<Ð	7ð Ø!%§¡¨Kô	@ð ˆr   c                ó0   <€ V ^8„  d   QhRS[ RS[RS[RR/# )r   r„	  rú  r	  r   N)rz  r8   r¨  )r   rä  s   "€r   r   rà  S  s1   ø€ ÷ ^ñ ^©|ð ^É#ð ^Ù!&ð^Ø15ñ^r   c                óÊ   € V P                  V4       V P                  P                  V4      pV P                  V\        P
                  ! V P                  WW44      4      4       R# )uÅ  Hand the session to a fresh task for a queued follow-up â€” never recurse (chained
follow-ups grew the C stack to SIGSEGV). Clearing (not deleting) the Event keeps the guard
live for concurrent inbound; ownership moves so stale-lock detection works. With ``delay``
the event stays in ``_pending_messages`` and the new owner task pops the slot only after
sleeping, so a cancel/discard during the back-off needs no put-back and can't drop a
newer message.N)rQ
  rø  r¥   rt	  r   rw  Ú_drain_after©rë  r„	  rú  r	  r_	  s   &&&& r   rC
  Ú%BasePlatformAdapter._spawn_drain_taskS  sW   € ð 	×!Ñ! +Ô.ð ×%Ñ%×)Ñ)¨+Ó6ˆØ× Ñ ØÜ×Ò × 1Ñ 1°-ÈeÓ [Ó\ö	^r   c          
      óZ   <€ V ^8„  d   QhRS[ RS[RS[RS[S[P
                  ,          RR/# )r   r„	  rú  r	  r_	  r   N)rz  r8   r¨  rf  r   rx  )r   rä  s   "€r   r   rà  c  sC   ø€ ÷ 	Kñ 	K±ð 	KÉ3ð 	KÑW\ð 	KÙ"*©7¯=©=Õ"9ð	KØ>Bñ	Kr   c              ƒ  ó.  "  € V^ 8”  dk   \         P                  ! V4      G Rj  x€L
  V P                  V4      G Rj  x€L
  V P                  P	                  VR4      pVf   V P                  W$4       R# V P                  W4      G Rj  x€L
  R#  Lk LT L
5irç   )r   r  rK	  rù  rã  rD
  rs	  rm
  s   &&&&&r   rl
  Ú BasePlatformAdapter._drain_afterc  sƒ   é € à�1Œ9Ü—-’- Ó&×&Ð&Ø×/Ñ/°Ó<×<Ð<Ø ×2Ñ2×6Ñ6°{ÀDÓIˆMØÒ$Ø×3Ñ3°KÔGÙØ×.Ñ.¨}ÓJ×JÒJñ 'Ù<ñ
 	Kùs2   ‚!B£B¤B¼B½ABÂBÂ	BÂBÂBc                ó$   <€ V ^8„  d   QhRS[ RR/# rY	  rk   )r   rä  s   "€r   r   rà  n  s   ø€ ÷ ñ ±ð ¸ñ r   c                óh   € V P                   P                  V4      pVe   VP                  4        R# R# )zUClear (not delete) the session's interrupt Event so the guard stays live for inbound.N)rø  r¥   Úclear)rë  rú  Ú_actives   && r   rQ
  Ú(BasePlatformAdapter._clear_session_guardn  s,   € à×'Ñ'×+Ñ+¨KÓ8ˆØÒØ�M‰MŽOñ r   c                óN   <€ V ^8„  d   QhRS[ RS[S[P                  ,          RR/# r:
  ra	  )r   rä  s   "€r   r   rà  t  s.   ø€ ÷ 8ñ 8Ùð8Ù19¹'¿-¹-Õ1Hð8ØMQñ8r   c                ó¾   € V P                  WR7       WP                  9  d;   V P                  P                  VR4       V P                  P                  VR4       R# R# )u<  Release a finished owner task's guard, dropping its ``_session_tasks`` entry ONLY if the
guard was released: after a concurrent guard swap the done-task entry lets
``_session_task_is_stale`` heal the orphan.

Release-then-conditional-delete is the #48300 fix: when a concurrent path (reset/new command, drain
handoff) swapped ``_active_sessions[key]`` to a different guard, ``_release_session_guard`` skips on
the guard mismatch and the lock stays installed. If we deleted ``_session_tasks`` unconditionally
(the old order), ``_session_task_is_stale`` would later see no owner task and report "not stale", so
the orphaned guard would never be healed â€” a permanent session deadlock. Keeping the done-task entry
when the guard survives lets the on-entry self-heal detect the stale lock and clear it on the next
inbound message.
rr	  N)rd	  rø  rý  rã  rú  )rë  rú  ro	  s   &&&r   rD
  Ú2BasePlatformAdapter._cleanup_finished_session_taskt  sR   € ð 	×#Ñ# KÐ#ÔGØ×3Ñ3Ô3Ø×Ñ×#Ñ# K°Ô6Ø× Ñ ×$Ñ$ [°$Ö7ñ 4r   c                ó   <€ V ^8„  d   QhRR/# r‘   rt   )r   rä  s   "€r   r   rà  ‡  s   ø€ ÷ ñ ¨tñ r   c           
   ƒ  ó  "  € \        ^4       F¯  pV P                   Uu. uF  q"P                  4       '       d   K  VNK  	  ppV'       g    MtV F.  pV P                  P	                  V4       VP                  4        K0  	   \        P                  ! \        P                  ! R V 4       RR/ RR7      G Rj  x€L
  K±  	  \        P                  ! \         4      ;_uu_ 4        ^ R	IHp V! V P&                  R
R7       RRR4       V P)                  4       P+                  4        F  pVP-                  4        K  	  V P                  V P                  V P.                  V P&                  V P0                  V P2                  V P)                  4       3 F  pVP5                  4        K  	  R# u upi  Ló  \         d8    \        P                  RT P                  \        R T 4       4      4         EK.  i ; i  + '       g   i     Lý; i5i)zuCancel in-flight background tasks (shutdown/replacement); 5s bound each,
stragglers are untracked and left to unwind.c              3   óN   "  € T F  p\         P                  ! V4      x € K  	  R # 5ir¼  )r   rµ  ©rì   r   s   & r   rï   Ú>BasePlatformAdapter.cancel_background_tasks.<locals>.<genexpr>•  s   é € Ð$FÁ¸1¤W§^¢^°A×%6Ð%6Ãùs   ‚#%Úreturn_exceptionsTrh   rÅ  Nzo[%s] %d background task(s) did not exit within 5s; releasing tracking and letting them unwind in the backgroundc              3   óL   "  € T F  qP                   ! 4       '       * x € K  	  R # 5ir¼  )r  r}
  s   & r   rï   r~
  š  s   é € Ð-JÁE¸q·&²&³(¯l©lÃEùrÃ  )Úflush_pending_to_fileÚadapter_shutdown)r*  )r  r  r  r  r©  r  r   rÍ  ÚgatherrÏ  r   rX   rF  Úsumr\   r]   r[   Úgateway.shutdown_flushr�
  rù  r.	  r�  r  rý  rø  rú  rt
  )rë  rí   r   Útasksr�
  rE	  Úbuckets   &      r   Úcancel_background_tasksÚ+BasePlatformAdapter.cancel_background_tasks‡  s™  é € ô
 �q–ˆAØ&*×&<Ò&<ÓPÑ&<˜dÇIÁIÇK—T�TÑ&<ˆEÐPßÙÛ�Ø×.Ñ.×2Ñ2°4Ô8Ø—‘–ñ ðÜ×&Ò&Ü—N’NÑ$FÁÓ$FÐ_ÐZ^Ñ_Øô!÷ !ò !ñ ô  × Ò ¤×+Õ+ÝDÙ! $×"8Ñ"8ÐASÕT÷ ,ð ×.Ñ.Ó0×7Ñ7Ö9ˆEØ×ÑÖ ñ :à×-Ñ-¨t×/MÑ/MÈt×ObÑObØ×-Ñ-¨t×/DÑ/DÀd×FZÑFZØ×0Ñ0Ó2ó4ˆFð �L‰LŽNó4ùò) Qñ!øô  ô Ü—‘ð  ^à#Ÿy™y¬#Ñ-JÁEÓ-JÓ*JôLô ð	ú÷
 ,×+üse   ‚HŸF'»F'ÁA HÂ6F.Â8F,Â9F.Â=&HÃ#G3Ã>B.HÆ,F.Æ.<G0Ç*HÇ/G0Ç0HÇ3H	Ç>Hc                ó&   <€ V ^8„  d   QhRS[ RS[/# rù  r´   )r   rä  s   "€r   r   rà  ¦  s   ø€ ÷ dñ d±ð d¹ñ dr   c                óp   € WP                   9   ;'       d"    V P                   V,          P                  4       # )z3Check if there's a pending interrupt for a session.)rø  r{  rl	  s   &&r   Úhas_pending_interruptÚ)BasePlatformAdapter.has_pending_interrupt¦  s-   € à×3Ñ3Ñ3×cÐc¸×8MÑ8MÈkÕ8Z×8aÑ8aÓ8cÐcr   c                ó6   <€ V ^8„  d   QhRS[ RS[S[,          /# rù  r„  )r   rä  s   "€r   r   rà  ª  s    ø€ ÷ =ñ =©sð =±xÁÕ7Mñ =r   c                ó:   € V P                   P                  VR4      # )z0Get and clear any pending message for a session.N)rù  rã  rl	  s   &&r   r°	  Ú'BasePlatformAdapter.get_pending_messageª  s   € à×%Ñ%×)Ñ)¨+°tÓ<Ð<r   c          $      óF  <€ V ^8„  d   QhRS[ RS[S[ ,          RS[ RS[S[ ,          RS[S[ ,          RS[S[ ,          RS[S[ ,          RS[S[ ,          R	S[S[ ,          R
S[RS[S[ ,          RS[S[ ,          RS[S[ ,          RS[S[ ,          RS[RS[RS[S[ ,          RS[/# )r   rC  Ú	chat_namerƒ   r  Ú	user_namer~   Ú
chat_topicr;	  Úchat_id_altr  r€   Úguild_idræ  r‡   Úrole_authorizedÚauto_thread_createdÚauto_thread_initial_namer   )r8   rf  rµ   r€  )r   rä  s   "€r   r   rà  ®  sí   ø€ ÷ *ñ *Ùð*Ù'/±¥}ð*ÙHKð*á™#•ð*á2:¹3µ-ð*ñ ™C•=ð*ñ 6>¹cµ]ð*ñ ™c•]ð	*ñ 9AÁ½ð	*ñ W[ð	*ñ
 ™3•-ð*ñ
 3;¹3µ-ð*ñ !¡�ð*ñ ;CÁ3½-ð*ñ ð*ñ =Að*ñ #+©3¥-ð*ñ <Iñ*r   c                óä  € R R lp\        V P                  \        V4      Y#Ve   VR8X  d   RM
\        V4      TV! V4      T;'       g    RP                  4       ;'       g    RVWšV! V4      V! V4      V! V4      V! V4      R7      p\	        V RR4      pTRRpppV P
                  e8   ^ RIHp  V P
                  P                  \        R/ VB VR	7      ;'       g    Tp\        R/ VBRVRVRVRV/B p\        P                  ! V 4      Vn        VVuVn        Vn        V#   T d   pR
TP                  pp Rp?L[Rp?i\         d'    \        P                  RT P                  TR
R7        LŽi ; i)zžBuild a SessionSource; with ``gateway.profile_routes`` configured the matching
profile is stamped on ``source.profile`` for per-profile HERMES_HOME isolation.c                ó:   € V ^8„  d   QhR\         \        ,          /# rj   r"  )r   s   "r   r   Ú6BasePlatformAdapter.build_source.<locals>.__annotate__¹  s   € ÷ 	1ñ 	1œ8¤C�=ñ 	1r   c                 ó,   € V '       d   \        V 4      # R # r¼  rk   rW  s   &r   Ú_optÚ.BasePlatformAdapter.build_source.<locals>._opt¹  s   € ß!&”3�u“:Ð0¨DÐ0r   Nrn   )rq   rC  r’
  rƒ   r  r“
  r~   r”
  r;	  r•
  r  r€   r–
  ræ  r‡   r	  F)ÚProfileRouteRejected)rß	  TzAProfile resolution failed for %s/%s, defaulting to active profiler   r‰   r—
  r˜
  r™
  rt   )r|   rq   r8   r‹   ro   r6  Úgateway.profile_routingr 
  Ú_profile_name_for_sourcer€  r‰   r[   r   rX   ÚweakrefÚrefÚ_transport_adapter_refrB  Ú_rejected_route_profile)rë  rC  r’
  rƒ   r  r“
  r~   r”
  r;	  r•
  r  r€   r–
  ræ  r‡   r—
  r˜
  r™
  rž
  ÚfieldsrÎ  r‰   rB  Úrejected_profiler 
  r   rŒ   s   &&&&&&&&&&&&&&&&&&         r   Úbuild_sourceÚ BasePlatformAdapter.build_source®  sœ  € õ	1äØ—]‘]¬C°«LÀIØ#šO¨w¸"¬}‘DÄ#ÀgÃ,Ø©4°	«?Ø"×(Ð( b×/Ñ/Ó1×9Ð9°TÀ{Ø#¹TÀ(»^Ù˜(“^±D¸Ó4HÙ˜JÓ'ô)ˆô   Ð&6¸Ó=ˆØ<IÈ5ÐRVÐ)9Ð'ˆØ×ÑÒ*ÝDðFØ×-Ñ-×FÑFÜ!Ñ+ FÑ+¸]ð Gó L÷ ]ð ]ØO\ð ô ñ R ñ R°ð RÈ/ð RØ3FðRà8PòRˆô
 )0¯ª°DÓ(9ˆÔ%ØH^Ð`pÐEˆÔ% vÔ'EØˆøð (ô MØ;?ÀÇÁÐ(8Ð&Ô(8ûÜô FÜ—‘ÐbØ#Ÿ}™}¨gÀð ö FðFús*   Â0,D! ÃD! Ä!E/Ä(D;Ä;E/Å$E/Å.E/c                ó<   <€ V ^8„  d   QhRS[ RS[S[ S[3,          /# r  )r8   r|   rg  )r   rä  s   "€r   r   rà  Û  s#   ø€ ÷ 4ñ 4©3ð 4±4¹¹S¸µ>ñ 4r   c              ƒ  ó   "  € R# 5i)zjGet information about a chat/channel; dict with at least ``name``
and ``type`` ("dm", "group", "channel").Nrt   r  s   &&r   Úget_chat_infoÚ!BasePlatformAdapter.get_chat_infoÚ  r×  rØ  c                óF   <€ V ^8„  d   QhRS[ RS[S[S[,          ,          /# rH  )r€  rf  r$  r8   )r   rä  s   "€r   r   rà  ß  s$   ø€ ÷ ñ ©-ð ¹HÁTÉ#ÅYÕ<Oñ r   c                ó   € R# )z¢Per-source toolset override REPLACING ``platform_toolsets.<platform>``, or None
(default); validated via ``_get_platform_tools`` (webhook adapter pins per-route).Nrt   )rë  rŒ   s   &&r   Útoolsets_for_sourceÚ'BasePlatformAdapter.toolsets_for_sourceß  s   € ñ r   c                ó&   <€ V ^8„  d   QhRS[ RS[ /# r¿  rk   )r   rä  s   "€r   r   rà  ä  s   ø€ ÷ ñ ¡cð ©cñ r   c                ó   € V# )zjFormat a message for this platform (override for e.g. Telegram
MarkdownV2); default returns content as-is.rt   )rë  r  s   &&r   Úformat_messageÚ"BasePlatformAdapter.format_messageä  s	   € ð ˆr   c          	      ój   <€ V ^8„  d   QhRS[ RS[RS[S[S[ .S[3,          ,          RS[S[ ,          /# )r   r  Ú
max_lengthrÙ   r   )r8   r9   rf  rh  r$  )r   rä  s   "€r   r   rà  ê  s@   ø€ ÷ <ñ <¡#ð <±3ð <Ù!)©(±C°5¹#°:Õ*>Õ!?ð<ÙKOÑPSÍ9ñ<r   c                ót  € T;'       g    \         pV! V 4      V8:  d   V .# ^
pRp. pT pRpV'       Ed7   Ve   RV R2MRp	W,
          V! V	4      ,
          V! V4      ,
          p
V
^8  d   \        ^V^,          4      p
V! V	4      V! V4      ,           W,
          8:  dB   W—,           pVe#   \        VRV4      ^ ,          '       d	   Wµ,          pVP                  V4       EM�V\         Jd   \	        WzV4      MT
pVRV pVP                  R4      pWì^,          8  d   VP                  R4      pV^8  d   \        ^V4      pVRV pVP                  R4      VP                  R	4      ,
          pV^,          ^8X  dˆ   VP                  R4      pV^ 8”  d+   VV^,
          ,          R
8X  d   VP                  R^ V4      pK1  V^ 8”  d?   \        VP                  R^ V4      VP                  R^ V4      4      pVV^,          8”  d   TpVRV pW~R P                  4       pV	V,           p\        TVRJT;'       g    R4      w  ppV'       d   TMRpTP                  V'       d
   VV,           MT4       EK?  \        V4      ^8”  d9   \        V4       UUu. uF!  w  ppV RV^,            R\        V4       R2NK#  	  pppV# u uppi )a  Split a long message into chunks preserving code blocks: a split inside a fence closes it
at the chunk end and reopens it (same language tag) in the next; multi-chunk output gets
``(1/3)`` indicators. ``len_fn`` overrides ``len`` (``utf16_len`` for Telegram).z
```Nz```r†  rn   TrÈ  Ú`z\`Ú\z (ré  rø  )	rÒ   r¯  rn  r­  rÝ   ÚrfindÚcountr}  rm  )r  r¸
  rÙ   Ú_lenÚINDICATOR_RESERVEÚFENCE_CLOSEr°  r€  Ú
carry_langr=   ÚheadroomÚfinal_chunkÚ	_cp_limitÚregionÚsplit_atr)  Úbacktick_countÚlast_btÚ
safe_splitÚ
chunk_bodyÚ
full_chunkÚin_codeÚlangrž  r²  s   &&&                      r   Útruncate_messageÚ$BasePlatformAdapter.truncate_messageé  s©  € ð �}ˆ}œˆÙ�‹=˜JÔ&Ø�9ÐØÐØˆØˆØˆ	Ø$(ˆ
ßˆiØ-7Ò-C�s˜:˜, bÑ)ÈˆFà!Õ5¹¸V»ÕDÁtÈKÓGXÕXˆHØ˜!Œ|Ü˜q *°¥/Ó2�á�F‹|™d 9›oÕ-°Õ1OÔOØ$Õ0�ØÒ)Ô.?À	È4ÐQ[Ó.\Ð]^×._Ô._ØÕ.�KØ—‘˜kÔ*Ùð BFÌSÃÔ" 9¸Ô=ÐV^ð à˜z 	Ð*ˆFØ—|‘| DÓ)ˆHØ q�.Ô(Ø!Ÿ<™<¨Ó,�Ø˜!Œ|ô ˜q )Ó,�à! ) 8Ð,ˆIØ&Ÿ_™_¨SÓ1°I·O±OÀEÓ4JÕJˆNØ Õ! QÔ&Ø#Ÿ/™/¨#Ó.�Ø ”k i°¸!µÕ&<ÀÔ&DØ'Ÿo™o¨c°1°gÓ>’GØ˜Q”;Ü!$Ø!Ÿ™¨¨Q°Ó8¸)¿/¹/È$ÐPQÐSZÓ:[ó"]�Jà! I°¥NÔ2Ø#-˜Ø" 9 HÐ-ˆJØ! )Ð,×3Ñ3Ó5ˆIØ *Õ,ˆJä-¨j¸*ÈDÐ:PÐR\×RbÐRbÐ`bÓc‰MˆG�Tß!(™¨dˆJà�M‰M·g˜* {Ö2À:×NÜˆv‹;˜Œ?ÜIRÐSYÔIZÔ[ÑIZ¹X¸QÀ˜˜˜r ! a¥% ¨¬#¨f«+¨°aÓ8ÑIZˆFÑ[Øˆùó \s   Ê'J4c                ó´  <€ V ^8„  d   Qh/ S[ ;R&   S[ ;R&   S[ ;R&   S[ ;R&   S[;R&   S[ ;R&   S[ ;R&   S[ ;R&   S[;R	&   S[S[,          ;R
&   S[;R&   S[;R&   S[;R&   S[;R&   S[;R&   S[;R&   S[;R&   S[ ;R&   S[;R&   S[;R&   S[;R&   S[;R&   S[;R&   S[S[S[3,          ;R&   S[S[,          ;R&   S[S[,          ;R&   S[S[,          ;R&   # )r   rd  Úsupports_status_textÚsupports_async_deliveryÚsplits_long_messagesrà	  Úsupports_inchannel_continuableÚinteractive_resumeÚserves_profile_prefixrà  rá  r  r^  ra  r\  r]  r_  r`  ÚREQUIRES_EDIT_FINALIZEr1  r2  r+  r&  r0  rD  Ú
_ACK_EMOJIr»  r¼  )rµ   r8   rg  rf  r&  r9   r¨  r|   )r   rä  s   "€r   r   rà  @  s¦  ø‡ ‚ ñ
 Ñ&ñ ñ Ñ&ñ ñ, "Ñ(ñ- ñ0 Ñ&ñ1 ñ4 Ñ#ñ5 ñ< %)Ñ0ñ= ñN Ñ#ñO ñX  Ñ'ñY ñ^  Ñ&ñ_ ñ` %¡S�MÑ0ña ñR Ñ ñS ñT  %Ñ*ñU ñV &+Ñ0ñW ñ^ "'Ñ,ñ_ ñ` #Ñ(ña ñb (-Ñ2ñc ñd $)Ñ.ñe ñD !Ñ(ñE ñr Ñ ñs ñt Ñ#ñu ñv Ñ%ñw ñx Ññy ñz Ññ{ ñF ™C¡˜H•~ÑMñG ñh2 ™•Ñ$ñi2 ñj2 ™�}Ñ#ñk2 ñl2 ™#•Ñ%òm2 r   ).rø  r  r  r  r  r  r  r   r  rþ  rõ  r  rò  rô  ró  rñ  r  rë  rì  r	  rù  rü  rû  rî  rÉ  rÈ  rö  r÷  rà  rá  r  rí  rú  rð  r#  rý  r
  râ  r  r^  ra  r  rï  r  rè  rq   )NNNr¼  rÆ  )ú...)rÙ
  N)NF)NNTTF)Nr¬  ©rn   )NNNN)rn   N)rO  NN)NNr   rO  r®  )Nr„   NNNNNNFNNNNFFN)r  N)órÎ  rï  rÏ  rð  rñ  rd  rÑ
  rå  rÒ
  rÓ
  rà	  rÔ
  rÕ
  rÖ
  r6  r  rG  r  r   r%  r)  r-  r2  r6  r;  rB  rP  ri  re  r˜  Úfatal_error_messageÚfatal_error_codeÚfatal_error_retryablerv  r|  r“  r€  rŒ  r‰  r™  r   rŠ  r¸  rÒ  rØ  rà  rá  rå  ré  rF  rñ  r÷  rý  r  r
  r  r  r  r  r$  r)  r.  r<  rE  rM  r  r^  ra  r\  r]  r_  r`  rV  rb  ri  rg  rr  rz  r�  r†  r‹  r�  rx  r¬  rÐ  r   rÕ  rÛ  rã  r×
  rè  rñ  rö  rý  r  r1  r2  r+  r&  r0  r  r  r  Ústaticmethodr  r  r"  r'  r,  r4  rD  r<  rE  ÚclassmethodrJ  rN  rI  r\  ra  rq  rw  r}  r�  r�  r”  r¬  r¥  r¤  r£  rÇ  rË  rÍ  rÛ  rÓ  rç  rÚ  ró  r÷  rý  r  r  r  r  r  r  r!  r&  r+  r5  r¢  rQ  r?  rG  r¨  r§  r`  rd  rs  r�  r‡  r|  rŽ  r’  r–  rž  r›  r¯  rØ
  r»  r¼  r³  rÀ  rÆ  rÑ  rÕ  rÝ  rä  rì  rò  rø  r~  ré  r
	  r	  r	  r	  r¯  r.	  r4	  r@	  rF	  rP	  rL	  rK	  r]	  rd	  rh	  rm	  ru	  rt	  r~	  r…	  r‹	  rŠ  r�	  r£	  r”	  r¹	  rÆ	  rÌ	  rÓ	  rã	  rñ	  r
  r
  r
  r
  r
  r#
  r)
  r/
  r7
  r?
  rG
  rs	  re
  rf
  rP
  rC
  rl
  rQ
  rD
  rˆ
  rŒ
  r°	  r©
  r­
  r±
  rµ
  rÎ
  rò  ró  rô  rõ  s   @r   r¦  r¦  @  s•  ø‡ € ÙVð "'Ðà!&Ð÷*ð *ð %)Ðà!&Ðà #Ðð ,1Ð"ð  $Ðð
 #(Ðð €N÷C/ð C/ðJ ÷ó ð÷
að a÷#ð #ð
 ÷ó ðð ÷ó ð÷ó ÷ó ÷
ð ÷Zó Z÷
+ð 
+ðv¸5ð vÐY[÷ vò v÷.ð ñ
 ÑQÓR€OÙ"Ñ#IÓJÐÙÑ CÓDÐÙ$Ñ%MÓNÐ÷[ð [÷,ð ,ð aÐà÷ó ððgÀ÷ gò g÷
ð 
÷dð d÷qð q÷3ð 3÷ ð ÷63ð 3÷j,ð ,ð #'ÐØ,0Ð÷1ó 1÷@@ð @ð ÷+ó ð+ð ÷ó ð÷(ð (÷/ð /÷%ð %÷Ið I÷&-ð -÷)ð )÷-ð -òØOTðà9=÷ó ÷4,ð ,÷
lð l÷
Kð K÷ð ÷0ð ÷Tó Tð> !ÐØ'*ÐØ-0Ð#ð *-ÐØ%(ÐØ/2Ð%Ø+.Ð!ðÐRUð Ðtx÷ ò ÷dð d÷6ð 6÷7ð 7÷.ð .÷_ð _÷*}ð }÷
9ð 9÷)ð )÷3ð 3÷>ð >÷6$5ð $5÷L,ð ,ð\ ðF°E÷ Fñ Fó ðFð
 ÷,ó ð,ð ÷`ò `ó ð`ð
 $)Ð÷ð ð@ØOT÷@ò @÷	ð 	÷Wð W÷ð ð, !€MØ#€NØ%ÐØ€NØÐà÷0ó ð0ð ÷-ó ð-ð ÷2ó ð2ð ÷Fò Fó ðF÷
ð ÷"ó "÷&#ð #÷uð u÷Ió Ið& *0°¸FÀHÐ(MÐà÷"ó ð"÷dð dð ÷dó ðd÷
=ó =÷$@ð @ð ÷(ó ð(÷@ó @÷Qó Q÷:gó g÷`ó `÷Xð Xð ÷Oó ðO÷(ó (÷"Fó "F÷Hdó d÷mó mð ÷:ó ð:ð ÷Bó ðB÷4Uó Uð
Fàcg÷
Fò 
FðWØ6:ðWØEIðWØ\`÷Wò Wð7Ø48ð7ØCGð7ØRVð7à÷7ò 7ò&ÐY]ð Ðgkð Ðvz÷ ó òPÈdð PÐ]a÷ Pó P÷

=ð 
=÷Wð W÷ð ÷ó ÷Ið Ið5Ð\a÷ 5ò 5÷có còMÐhl÷ Mó MòRÐsw÷ Rô Rò
kÐnr÷ kõ k÷Uõ U÷kõ kñfØAFðfà-1÷fô f÷2Zõ Zð ÷Kô Kó ðKð ÷rô ró ðrð ÷,ô ,ó ð,ð
 ÷,ñ ,ó ð,ð* ÷,ñ ,ó ð,ð( ÷&ñ &ó ð&ðP ÷Uñ Uó ðUð ÷Hñ Hó ðH÷@&Fõ &FòP1ØQUñ1áñ1à34÷1õ 1÷$Eõ E÷
)ò )÷-ò -÷;õ ;ñMØPT÷Mô Mð( ÷ñ ó ðñ
8Ø<@÷
8ô 
8ð !%€JØ#€IØ!%€K÷=ò =÷2ò 2÷*Oò Oð ÷Hñ Hó ðHð
 ÷Hñ Hó ðHð ÷[ñ [ó ð[÷,ò ,ñ^Ð\`÷ ^ô ^÷"
,ò 
,÷ò ð  ÷xô xó ðx÷tò ð
 ÷Kñ Kó ðK÷ò ÷2ò 2ð ÷8ñ 8ó ð8÷8ò 8÷	ò 	÷Sò S÷"5ò 5÷Xò X÷B"ò "÷ò ÷.ò .ñ/Ð[_÷ /ô /÷%ò %÷ò ñØMQ÷ô ÷ò ñ5ÐY]ñ 5Ø@D÷5ô 5÷8Gò G÷Tò T÷.*Uò *U÷Xbò b÷
ò ÷"e+ò e+÷N8ò 8÷%ò %÷.^ò ^÷Gò G÷ ò  ÷DIò I÷>3_ò 3_÷j ò  ñ(à?D÷(ô (÷2Jò J÷	pò 	p÷ ò  ÷,Kò K÷*
Vò 
V÷0iò 0i÷d
jò 
j÷Nò N÷0{Dò {Dñz (,Ð$ð $'Ð ÷ò ÷<^õ ^÷ 	Kò 	K÷ò ÷8ò 8÷&ò ÷>dò d÷=ò =÷*õ *ðX ÷4ñ 4ó ð4÷ò ÷
ò ð
 ÷<ô <ó ð<÷U] … r   r¦  c                óþ  € V ^8„  d   Qh/ ^ \         9   d)   \        \        \        R,          3,          R,          ;R&   ^\         9   d   \        \        R3,          ;R&   ^\         9   d   \        \        \        3,          ;R&   ^\         9   d,   \        \
        P                  \        ,          R3,          ;R&   ^\         9   d:   \        \        \        \        \        .\        3,          3,          R3,          ;R&   # )r   Nr  .r—  rú  r7  r…  )	Ú__conditional_annotations__r%  r¨  r8   r|   r�  ÚPatternrh  rµ   )r   s   "r   r   r      sÛ   € × `Ñ `÷h ;Ò :”Eœ%¤ t¥Ð+Õ,¨tÕ3Ñ :ñi a÷V&	ò 	”Uœ3 ˜8•_ñ 	ñW& a÷F/.ò .Œd”3œ�8�nñ .ñG/ a÷z1Lò L¤U¬2¯:©:´c­?¸CÐ+?Õ%@ñ Lñ{1 a÷z4Wò Wœœu¤S¬(´C°5¼$°;Õ*?Ð%?Õ@À#ÐEÕFñ Wò{4 ar   >   ú.3gpr)   r*   r(   r'   r+   >   r0   r,   r.   r-   r/   r¼  >   r  r§   r©   r¨   rf  i   )r,   )r,   r   )r    )r    r   )r'   )r”  r2  rA  rJ  rK  )	z/etcz/procz/sysz/devr6  z/bootz/var/logz/var/libz/var/run)	z.sshz.awsz.gnupgz.kubez.dockerz.configz.azurez.gcloudzLibrary/KeychainsrÚ
  >   r@   rA   Úyesr  ):r.   r,   r-   r0   r/   z.bmpz.tiffz.svgr'   r(   r)   r*   r+   rã
  r"   r#   r$   r    r!   r%   r&   rg  rs  rp  z.odtz.rtfri  rh  z.epubrt  rq  z.odsrj  rv  rk  rl  rm  rn  z.kmzz.kmlz.geojsonz.gpxru  rr  z.odpz.keyro  z.tarz.gzz.tgzz.bz2z.xzz.7zz.rarz.apkz.iparw  rx  >   rƒ  rR  rT  rU  rW  rS  rV  )zchat not found)zmessage to edit not foundzmessage to reply not foundzthread not foundÚtopic_deletedÚmessage_id_invalid)Nrn   )	ÚconnecterrorÚconnectionerrorÚconnectionresetÚconnectionrefusedr|  Únetworkzbroken pipeÚremotedisconnectedÚeoferror(&  rá
  rñ  r   r\   r‡  ré   ÚloggingrT  rP   r	  r�  Úsocketrò   rS   r  rN   rË  r  rÈ   r£
  Úabcr   r   Úhermes_dir_aclr   r   Ú!gateway.platforms.base_log_safetyr   Úutilsr   Ú
agent.i18nr   Úagent.retry_utilsr	   Úagent.proxy_bypassr
   r   r)  Ú	getLoggerrÎ  r   r   r  Ú	frozensetr·   r1  rù	  r¸   Ú_TELEGRAM_VOICE_EXTSrf   r<
  rÎ  Ú!_HISTORY_MEDIA_LOOKUP_MAX_WORKERSÚBoundedSemaphorerÇ  rr   rž  rñ   rw   rÿ  r  r�   r—   rœ   r”   r®   r°   rº   rÎ   rÔ   rÝ   rá   rû   r  r  r  r!  r3  r>  rD  rM  r0  rZ  r_  Údataclassesr`  Úpathlibrb  Útypingrc  rd  re  rf  rg  rh  ri  rj  rk  r6   Úinsertr8   Ú__file__rÌ  rà  Úgateway.configrl  rm  Úgateway.platforms.helpersrn  Ú$gateway.platforms.base_exec_approvalro  rp  rq  rr  rs  rt  ru  Ú$gateway.platforms.base_streaming_ttsrv  rw  rx  ry  Úgateway.platforms.eventrz  r{  r|  rë  r}  Ú/hermes_cli.observability.shared_metrics_gatewayr~  r  Úgateway.sessionr€  r�  Úgateway.session_transcriptr‚  Úhermes_constantsrƒ  r„  r…  r†  Úagent.provider_mediar‡  rˆ  rb  r‰  Ú*GATEWAY_SECRET_CAPTURE_UNSUPPORTED_MESSAGEÚUNAUTHORIZED_ACTION_NOTICErŒ  r“  rÑ  rœ  rŸ  r¦  r³  rÐ  rú  Úcleanup_image_cacherÛ  r¿  rñ  rü  r  r  r&  rÇ  r3  r8  Úcleanup_audio_cacher9  r<  r@  rB  rE  Úcleanup_video_cacher  rF  rI  rM  rO  rÚ  Úcleanup_document_cacheÚget_screenshot_cache_dirÚcleanup_screenshot_cacher¾  rZ  rx  ÚMEDIA_DELIVERY_ALLOW_DIRS_ENVÚMEDIA_DELIVERY_TRUST_RECENT_ENVÚ'MEDIA_DELIVERY_TRUST_RECENT_SECONDS_ENVÚMEDIA_DELIVERY_STRICT_ENVrl  r£  r²  rÄ  rÅ  rb  rÆ   rÀ  rt  rs  r~  r„  r‰  r•  r¥  r³  r·  rÆ  rÎ  r×  rÛ  rÓ  rä  r÷  r  r  r	  r  r  r   r'  r.  rF  rQ  rk  rW  r-  rb  r_  r  Ú_TEXT_INJECT_EXTENSIONSr  r—  r=  rÒ   Ú_MEDIA_EXT_ALTERNATIONÚ_MEDIA_CJK_TERMINATORSrl  r¼  r´  r’  rM  r˜  rŸ  r¢  r£  r¬  r±  r¶  r¯  rò  rÁ  rÂ  rÄ  r©  rÎ  rÒ  rÝ  rà  râ  rÌ  Úitemsrú  rû  r  r  r  r$  r&  r7  r8  r:  rI  r	  ÚSEND_ERROR_KINDSrw  rx  rb  rk  r…  r‡  rŠ  rŒ  r»  r}  rõ  rÆ  rÔ  r×  rÝ  r3
  r¦  r   )r  r²   r  rá
  s   000@r   Ú<module>r     s¹  øðß `Ð `ã Û Û Û Û Û Û 	Û Û 	Û Û Û 
Û Û Û Û Û ß #ß =Ý >å %Ý Ý .ß aà	×	Ò	˜8Ó	$€õXð ˆK˜ ,°¸ÀfÈlØ
ˆK˜ ¨g°|ðEÐ ñ Ð)Ó*€áÓIÓJ€ÙÓBÓC€á"+¨V°VÐ,<Ó"=Ð Ù  &¨'Ð!2Ó3Ð ð!°uð !ÈRð !Ø48÷!ðD +/Ð 'à(+Ð %ð %&Ð !Ø"+×"<Ò"<Ð=^Ó"_Ð õ$ð &/°
Ð$;ô ð &*Ð "Ø%(Ð "÷ð õ:Uõ
õ.ñ2 Ó@ÓAÐ ÷Fð F÷
Ið 
Iõõ&+õõ7õ
ð,  Ð Ø6:Ð Ó :õ õFõ.òJàHLðJð "÷Jð Jõ8õ õ8õ6õ	]÷Ið Ió Ý !Ý ß ^× ^Õ ^à ‡�‡��‘3‘t˜H“~×-Ñ-Ó/×7Ñ7¸Õ:Ó;Ô <ç 3Ý 7÷R÷ Rñ R÷có cç PÑ PÝ ?ß ^ß <Ý :ß qÓ qß LçÝ)ðbð +ðið õ
Wòlñ ! °Ó?€ñ #4Ð õ[ðfØ$+ðfØHL÷fõõ*ñ* ,@ØÐ °ó,?Ñ (Ð Ð(õWõ"5õJ÷(Fð F÷Fð Fõ
÷<<ð <õ	ñ ! °Ó>€Ù+?ØÐ ¨}ó,>Ñ (Ð Ð(÷_ð _÷Fð F÷
<ð <ñ ! °Ó?€Ù+?ØÐ °ó,?Ñ (Ð Ð(ð ˆK˜Ð!2°G¸\Ø
Ð Ð(9ð;Ð ÷
Hð H÷Fð Fñ $Ð$5Ð7GÓHÐ Ù%Ð&9Ð;PÓQÐ Ù1EØÐ$Ð&7Ð9Ió2KÑ .Ð Ð.á5IØÐ(Ð*=Ð?Tó6VÑ 2Ð Ð2ð
 �Ð(9¸?Ø�Ð(<Ð>PØÐ0ð2Ð ñ Ó €Ù&Ó(€Ø 9Ð Ø"CÐ Ø*MÐ 'ð ;Ð ð ˆg�x ¨mÐ=Mð!OÐ ð �_ oÐ7IÐK_ðJñ_ò !^ó _ðJñ
 IÑ*GÓHñJÐ ð 03Ð ,ñ#[Ð ñ(Ð $õCð ˆK˜ m°]ÐD[ØÐ4°b·g±g·l²lÀ6ÐK^Ó6_Ø  "§'¡'§,¢,¨wÐ8HÓ"IØ‡G�G‡L‚L�Ð.Ó/°¸Lð Ð!ð\ñ %2°*Ó$=ð\ñ ANÈkÓ@Zñ\Ð õ^õõTõ_õ
õ	õ:õXõcõ'ð°ð Àe÷ õõ õ÷'ð 'õ÷4ð ó> %€õAõnõ
÷Fð Fõ	÷Jñ Jó&Ðdi÷ &ò &÷R$ò $ðR —J“JÑAÓBÐ ÷7÷
ò ÷*ð
CÙ
Ñð
CÙ$¡oð
CÙ7=¹|ð
CÙMSÑU_ð
Cá
‰Lð
Cá!Ñ#5ð
Cá7=Ñ?Pð
Cñ Ñð
Cñ "(Ñ);ð
Cñ >EÑFXð
Cñ ‰Lð	
Cñ !¡,ð	
Cñ 17Ñ8Ið	
Cñ
 Ñ ð
Cñ
 #)Ñ*Dð
Cñ Ñ+ð
Cñ ÑVð
Cñ ÑPÙÑXÙ	‰<™¡©e±\ñ
CÐ ðÙ
ðÙðÙðÙ &ðÙ(.ðÙ06ðÙ8?ðÙAIðÙKTðÙV\ðáðáðáðá$ðá&,ðá.5ðà7=ðá?LðáNUðáW]ðñ ðñ ðñ ðñ &ðñ (-ðñ /5ðñ 7<ðñ >Dðñ FLðñ NSðñ U[ðñ ]cðñ 
ð	ñ ð	ñ ð	ñ $ð	ñ &,ð	ñ .4ð	ñ 6:ð	ñ <@ð	ñ BHð	ñ JOð	ñ QWð	ñ Y^ð	ñ
 ðñ
 ðñ
 ðñ
 !ðñ
 #(ðñ
 *0ðñ
 27ðñ
 9?ðñ
 AEðñ
 GLðñ
 NVðñ
 X\ðñ ðñ ðñ ðñ $ðñ &,ðñ .4ðñ 6@ðñ BJðñ LQðñ SYðñ ðñ ðñ !)ðñ +4ðñ 6<ðñ >Dðñ FLðñ NTðñ V]ðñ ðÐ ð ‰L˜'¡<°¹ÀgÉ|Ø
‰Kð"Ð ñ&	(Ð ó 	ñ Ÿš¡&Ò)UÑATÓ)UÐ[^ÑhlÕ"mÓnÐ ñ2 aÐ à—z“zñ>à@VõWñZ õ ð #9õ9ñ <hõhð ‡M‚MóÐ ð8  ŸZ›Zñð 5õ5ñ8õð
 ‡M‚MóÐ ÷ ÷F5÷	@÷Yñ Ð ÷(÷	÷÷6÷ð —*“*Ñ1°2·9²9Ó=€Ø—*“*™\Ó*€÷a÷
÷ð ÷"Cð C÷ð ÷ Nð Nð ÷iò ió ñið& +Ð,AÐCaÑbõ .ábˆÚ˜eŸkšk›mÖ,‰	ˆð 	‚Iá,ñ 	Ùbó .�ó .÷Bð BñM°bñ MÈ2ñ MØ48÷Mò Mñ@ð ñð ñ	ð
 #'÷ò ð" ÷	ò 	ó ñ	÷5ð 5ð
 ÷ò ó ñð ‡JƒJÑFÈÏÊÓVØ‡JƒJÑOÐQS×Q^ÒQ^Ó_Ø‡JƒJÑ:¸B¿MºMÓJðDLÑ #ó L÷$ð $ð  ÷9ò 9ó ñ9ð( ÷%ò %ó ñ%ð* $(Ñ  ñ Û`óbÑ ñ
 $7Ñ  ñ!Ñ ÷
#ó #÷+ð +ñ Ò\Ð]Ùò 2ð 3ñ ò ?ð @ñ ÒiÐjÙÒdÐeÙÒTÐUðJWÑ ó W÷aó a÷Bó Bö!�Sõ !ñ$.*ØKP÷.*ò .*ñf@Ñ ð
 ˜<˜.¨)°H¸UÀ3ÑHXÐCXÕ=YÕ4ZÕ*[Ð[Õ\�÷
ó 
÷ó ÷.Tð T÷ð ñ 6Ñ öf/˜#÷ f/ùôy
 .s   à,,i