+
    jHàjLv  ã            
       ó¸  € 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H	t	 ^ RI
HtHtHt ^ RIHt ^ RIHt ]P$                  ! ]4      t ! R R4      tR R	 ltR
 R lt]P0                  tR R ltR R lt]P8                  ! R]P:                  4      R3]P8                  ! R]P:                  4      R3]P8                  ! R]P:                  4      R3]P8                  ! R]P:                  4      R3]P8                  ! R4      R3]P8                  ! R4      R3]P8                  ! R]P<                  4      R33t]P8                  ! R4      t ]P8                  ! R]PB                  4      t"]P8                  ! R4      t#R R lt$RR/R  R! llt% ! R" R#4      t&R$ R% lt'R& R' lt(]P8                  ! R(4      t)R) R* lt*R+ R, lt+R- R. lt,R/ R0 lt-R1RR2RR3RR4R/R5 R6 llt.R7 R8 lt/R9 R: lt0R; R< lt1R= R> lt2R? R@ lt3]P8                  ! RA4      t4RB t5RZRC lt6RD RE lt7RF RG lt8RH RI lt9RJ RK lt:R[RL RM llt;R\RN lt<RZRORPRQR/RR llt=RZRS lt>RT t?R]t@RUtARV RW ltBRX RY ltCR# )^uÆ   Shared helpers for gateway platform adapters: message dedup, markdown
stripping, thread participation tracking, GFM table â†’ bullets, mention-pattern
compilation, and fence-aware markdown chunking.N©ÚPath)ÚAnyÚMutableMappingÚOptional)ÚMessageEvent)Úatomic_json_writec                   óˆ   a € ] tR t^t o Rt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	V 3R lR lt
RtV tR# )ÚMessageDeduplicatorzRTTL-based message deduplication cache (``if dedup.is_duplicate(msg_id): return``).c                ó&   <€ V ^8„  d   QhRS[ RS[/# )é   Úmax_sizeÚttl_seconds)ÚintÚfloat)ÚformatÚ__classdict__s   "€Ú>/home/ubuntu/.hermes/hermes-agent/gateway/platforms/helpers.pyÚ__annotate__Ú MessageDeduplicator.__annotate__   s   ø€ ÷  ñ  ¡ð  ¹%ñ  ó    c                ó,   € / V n         Wn        W n        R # ©N)Ú_seenÚ	_max_sizeÚ_ttl)Úselfr   r   s   &&&r   Ú__init__ÚMessageDeduplicator.__init__   s   € Ø')ˆŒ
Ø!ŒØŽ	r   c                ó&   <€ V ^8„  d   QhRS[ RS[/# ©r   Úmsg_idÚreturn©ÚstrÚbool)r   r   s   "€r   r   r      s   ø€ ÷ ñ ¡3ð ©4ñ r   c                ó¨  € V'       g   R# \         P                   ! 4       pWP                  9   d8   W P                  V,          ,
          V P                  8  d   R# V P                  V W P                  V&   \        V P                  4      V P                  8”  d´   W P                  ,
          pV P                  P                  4        UUu/ uF  w  rEWS8”  g   K  WEbK  	  uppV n        \        V P                  4      V P                  8”  dC   \        \        V P                  P                  4       R R7      V P                  ) R 4      V n        R# u uppi )z?Return True if *msg_id* was already seen within the TTL window.FTc                 ó   € V ^,          # )é   © )Úitems   &r   Ú<lambda>Ú2MessageDeduplicator.is_duplicate.<locals>.<lambda>+   s	   € ÈdÐSTÎgr   )ÚkeyN)Útimer   r   Úlenr   ÚitemsÚdictÚsorted)r   r!   ÚnowÚcutoffÚkÚvs   &&    r   Úis_duplicateÚ MessageDeduplicator.is_duplicate   sî   € çÙÜ�iŠi‹kˆØ—Z‘ZÔØ—Z‘Z Õ'Õ'¨$¯)©)Ô3ÙØ—
‘
˜6Ð"Ø �
‰
�6ÑÜˆt�z‰z‹?˜TŸ^™^Ô+ØŸ9™9•_ˆFØ+/¯:©:×+;Ñ+;Ô+=ÔLÑ+=¡4 1ÀÁœ$˜!š$Ñ+=ÒLˆDŒJÜ�4—:‘:‹ §¡Ô/ä!¤&¨¯©×)9Ñ)9Ó);ÑAUÔ"VÐX\×XfÑXfÐWfÐWgÐ"hÓi�”
Ùùó	 Ms   Ã
EÃEc                ó&   <€ V ^8„  d   QhRS[ RS[/# r    r#   )r   r   s   "€r   r   r   .   s   ø€ ÷ ñ ™sð ¡tñ r   c                óÐ   € V'       d   V P                   P                  V4      MRpVf   R# \        P                  ! 4       V,
          V P                  8  d   R# V P                   V R# )zBReturn whether *msg_id* is live in the cache without inserting it.NFT)r   Úgetr.   r   )r   r!   Úseen_ats   && r   ÚcontainsÚMessageDeduplicator.contains.   sI   € ç,2�$—*‘*—.‘. Ô(¸ˆØŠ?ÙÜ�9Š9‹;˜Õ  4§9¡9Ô,ÙØ�J‰J�vÐÙr   c                ó$   <€ V ^8„  d   QhRS[ RR/# )r   r!   r"   N©r$   )r   r   s   "€r   r   r   8   s   ø€ ÷ %ñ %™cð % dñ %r   c                ó>   € V P                   P                  VR4       R# )z<Release a claimed message ID after cancelled/failed handoff.N)r   Úpop)r   r!   s   &&r   ÚdiscardÚMessageDeduplicator.discard8   s   € à�
‰
�‰�v˜tÖ$r   c                ó:   € V P                   P                  4        R # r   )r   Úclear©r   s   &r   rF   ÚMessageDeduplicator.clear<   s   € Ø�
‰
×ÑÖr   c                ó"   <€ V ^8„  d   QhRRRR/# )r   Úotherr
   r"   Nr)   )r   r   s   "€r   r   r   ?   s    ø€ ÷ hñ hÐ1ð h°dñ hr   c                ó   € \         P                   ! 4       V P                  ,
          pV P                  P                  VP                  P	                  4        UUu/ uF!  w  r4WB8”  g   K  W0P                  9  g   K  W4bK#  	  upp4       R# u uppi )zNAdopt *other*'s still-live IDs (at their original seen times) into this cache.N)r.   r   r   Úupdater0   )r   rJ   r4   r5   r6   s   &&   r   ÚabsorbÚMessageDeduplicator.absorb?   sa   € ä—’“˜tŸy™yÕ(ˆØ�
‰
×Ñ¨E¯K©K×,=Ñ,=Ô,?ÔfÑ,?¡D AÀ1Á:œ4ÐRS×[eÑ[eÑReœ4˜1š4Ñ,?ÒfÖgùÓfs   Á
B

Á(B

Á:B

)r   r   r   N)iÐ  i,  )Ú__name__Ú
__module__Ú__qualname__Ú__firstlineno__Ú__doc__r   r7   r=   rC   rF   rM   Ú__static_attributes__Ú__classdictcell__©r   s   @r   r
   r
      sA   ø‡ € Ù\÷ ò  ÷
ð ÷$ð ÷%ð %ò÷hö hr   r
   c                ó4   € V ^8„  d   QhR\         R\         RR/# )r   ÚpredecessorÚadapterr"   N©r   )r   s   "r   r   r   E   s!   € ÷ %ñ %¤Sð %´3ð %¸4ñ %r   c                óþ   € V f   R# \        V 4      P                  4        FY  w  r#\        WR4      p\        V\        4      '       g   K)  \        V\        4      '       g   KA  WCJg   KH  VP                  V4       K[  	  R# )a5  Seed a rebuilt adapter's dedup caches from the instance it replaces (call before connect).

The runner's reconnect path builds a NEW adapter; without this a platform replaying a recent
inbound ID after the reconnect (websocket resume, webhook retry, unacked poll batch) is
admitted and answered a second time.N)Úvarsr0   ÚgetattrÚ
isinstancer
   rM   )rX   rY   ÚnameÚpreviousÚcurrents   &&   r   Úcarry_inbound_deduprb   E   s`   € ð ÒÙÜ˜{Ó+×1Ñ1Ö3‰ˆÜ˜'¨Ó.ˆÜ�hÔ 3×4Ô4¼ÀGÔM`×9aÔ9aÐfmÕf}Ø�N‰N˜8Ö$ó 4r   c                ó4   € V ^8„  d   QhR\         R\         RR/# )r   ÚsourceÚtargetr"   NrZ   )r   s   "r   r   r   S   s!   € ÷ ñ ¤3ð ´ð ¸ñ r   c                ób   € \        VRR4      pV e   \        V4      '       d   V! V 4       R# R# R# )a`  Move inbound ``source`` is holding to ``target`` (#132829, #133399).

The runner calls it at publish time (retired instance -> replacement) and after disposing a
failed reconnect candidate (candidate -> retained predecessor): a candidate that fails connect
can hold acked updates and salvage pending batches in disconnect(), which must not die with it.Úadopt_held_inboundN)r]   Úcallable)rd   re   Úadopts   && r   Úhand_over_held_inboundrj   S   s0   € ô �FÐ0°$Ó7€EØÒœh uŸošoÙˆfŽñ .Ñr   c                óR   € V ^8„  d   QhR\         \        P                  ,          RR/# )r   Útaskr"   N)r   ÚasyncioÚTask)r   s   "r   r   r   d   s#   € ÷ 	ñ 	œH¤W§\¡\Õ2ð 	°tñ 	r   c              ƒ  óP  "  € V e   V P                  4       '       d   R# V P                  4        V \        P                  ! 4       JdG   \        P
                  ! \        P                  \        4      ;_uu_ 4        V G Rj  x€L
  RRR4       R# R#  L  + '       g   i     R# ; i5i)zûCancel *task* and wait for it to unwind. ``None``/finished tasks are no-ops; awaiting the
current task would deadlock, so a self-cancel only requests cancellation. Exceptions the task
dies with are swallowed: at teardown nobody is left to handle them.N)ÚdoneÚcancelrm   Úcurrent_taskÚ
contextlibÚsuppressÚCancelledErrorÚ	Exception)rl   s   &r   Úcancel_taskrw   d   sp   é € ð ‚|�t—y‘y—{’{ÙØ‡K�K„MØ”7×'Ò'Ó)Ó)Ü× Ò ¤×!7Ñ!7¼×CÕCØ�JˆJ÷ DÑCñ *á÷ D×CÐCüs5   ‚B&�AB&Á9BÁ?BÂ BÂB&ÂBÂB#	Â	B&c          
      ón   € V ^8„  d   QhR\         \        \        3,          R\        R\        R\        RR/# )r   Ústorer-   ÚvalueÚcapr"   N)r   r$   r   r   )r   s   "r   r   r   p   s9   € ÷ %ñ %”~¤c¬3 hÕ/ð %´cð %Ä#ð %ÌCð %ÐTXñ %r   c                ó€   € V P                  VR4       W V&   \        V 4      V8”  d   V \        \        V 4      4       K'  R# )z¬Insert into an insertion-ordered mapping with a hard size bound, evicting the oldest keys. A
re-put moves the key to the newest position so live entries outlast stale ones.N)rB   r/   ÚnextÚiter)ry   r-   rz   r{   s   &&&&r   Úbounded_putr   p   s;   € ð 
‡I�Iˆc�4ÔØˆ#�JÜ
ˆe‹*�sÔ
Ø”$”t˜E“{Ó#Ò$ñ r   z\*\*(.+?)\*\*ú\1z	\*(.+?)\*z \b__(?![\s_])(.+?)(?<![\s_])__\bz\b_(?![\s_])(.+?)(?<![\s_])_\bz```[a-zA-Z0-9_+-]*\n?Ú z`(.+?)`z
^#{1,6}\s+z\[([^\]]+)\]\(([^\)]+)\)z	https?://z\n{3,}c                óZ   € V ^8„  d   QhR\         P                  \        ,          R\        /# )r   Úmatchr"   )ÚreÚMatchr$   )r   s   "r   r   r   Š   s"   € ÷ ?ñ ?œRŸX™X¤c�]ð ?¬sñ ?r   c                óò   € V P                  ^4      P                  4       V P                  ^4      P                  4       r!\        P                  V4      '       g   V P                  ^4      # W8X  d   V# V RV 2# )aT  ``[label](https://url)`` -> ``label\nurl``.

The bare URL is the only thing a platform with its own data detection
(iMessage) can turn back into a tap target, so dropping it makes the link
unreachable rather than merely unformatted. Non-http targets (``mailto:``,
relative paths) are not auto-linked, so they keep the label-only behaviour.
Ú
)ÚgroupÚstripÚ_HTTP_TARGET_RErƒ   )rƒ   Úlabelre   s   &  r   Ú_keep_link_targetrŒ   Š   sf   € ð —K‘K “N×(Ñ(Ó*¨E¯K©K¸«N×,@Ñ,@Ó,Bˆ6Ü× Ñ  ×(Ò(Ø�{‰{˜1‹~ÐØ”_ˆ6Ð>¨U¨G°2°f°XÐ*>Ð>r   Úkeep_link_targetsFc                ó<   € V ^8„  d   QhR\         R\        R\         /# )r   Útextr�   r"   r#   )r   s   "r   r   r   ˜   s!   € ÷ 	9ñ 	9œð 	9´Dð 	9ÄSñ 	9r   c               óÒ   € \          F  w  r#VP                  W04      p K  	  \        P                  V'       d   \        MRV 4      p \        P                  RV 4      P                  4       # )zãStrip markdown formatting for plain-text platforms (SMS, iMessage, etc.).

``keep_link_targets`` rewrites ``[label](https://url)`` as ``label\nurl``
instead of discarding the URL; pass it on platforms that auto-link bare URLs.
r€   ú

)Ú_STRIP_RULESÚsubÚ_MD_LINK_RErŒ   Ú_NEWLINE_SQUEEZE_REr‰   )r�   r�   ÚpatternÚrepls   &$  r   Ústrip_markdownr˜   ˜   sP   € ÷ &‰ˆØ�{‰{˜4Ó&Šñ &ä�?‰?×0AÕ,ÀuÈdÓS€DÜ×"Ñ" 6¨4Ó0×6Ñ6Ó8Ð8r   c                   óÎ   a € ] tR t^¤t o RtRt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	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R ltV 3R lR ltRtV tR# )ÚThreadParticipationTrackerz¦Persistent set of threads the bot has participated in (``<platform>_threads.json``);
``thread_id in tracker`` checks membership, ``tracker.mark(thread_id)`` persists.éô  c                ó&   <€ V ^8„  d   QhRS[ RS[/# )r   Úplatform_nameÚmax_tracked)r$   r   )r   r   s   "€r   r   Ú'ThreadParticipationTracker.__annotate__ª   s   ø€ ÷ Uñ U¡cð U¹ñ Ur   c                óä   € Wn         W n        \        P                  ! 4       V n        \        P                  ! 4       V n        \        P                  R  V P                  4        4       4      V n	        R# )c              3   ó8   "  € T F  p\        V4      x € K  	  R # 5ir   r@   )Ú.0Úts   & r   Ú	<genexpr>Ú6ThreadParticipationTracker.__init__.<locals>.<genexpr>º   s   é € Ð6TÁ|À!´s¸1·v°vÃ|ùs   ‚N)
Ú	_platformÚ_max_trackedÚ	threadingÚLockÚ_lockÚ_io_lockr1   ÚfromkeysÚ_loadÚ_threads)r   r�   rž   s   &&&r   r   Ú#ThreadParticipationTracker.__init__ª   sG   € Ø&ŒØ'Ôô —^’^Ó%ˆŒ
Ü!ŸšÓ(ˆŒÜ)-¯©Ñ6TÀtÇzÁzÄ|Ó6TÓ)TˆŽr   c                ó    <€ V ^8„  d   QhRS[ /# ©r   r"   r   )r   r   s   "€r   r   rŸ   ¼   s   ø€ ÷ Dñ D™Tñ Dr   c                óD   € ^ RI Hp V! 4       V P                   R2,          # )é    )Úget_hermes_homez_threads.json)Úhermes_constantsr´   r¦   )r   r´   s   & r   Ú_state_pathÚ&ThreadParticipationTracker._state_path¼   s   € Ý4ÙÓ  d§n¡nÐ%5°]Ð#CÕCÐCr   c                ó0   <€ V ^8„  d   QhRS[ S[,          /# r±   ©Úlistr$   )r   r   s   "€r   r   rŸ   À   s   ø€ ÷ Xñ X‘t™C•yñ Xr   c                ó  €  \         P                  ! V P                  4       P                  R R7      4      p\        T\        4      '       d   T Uu. uF  p\        T4      NK  	  up# . #   \         d    . u # i ; iu upi )z	utf-8-sig)Úencoding)ÚjsonÚloadsr¶   Ú	read_textrv   r^   rº   r$   )r   ÚdataÚ	thread_ids   &  r   r­   Ú ThreadParticipationTracker._loadÀ   sr   € ð	Ü—:’:˜d×.Ñ.Ó0×:Ñ:ÀKÐ:ÓPÓQˆDô :DÀDÌ$×9OÒ9O±Ó5± 9”�I–±Ñ5ÐWÐUWÐWøô ô 	ØŠIð	üâ5s   ‚4A) ÁA<Á)A9Á8A9c                ó   <€ V ^8„  d   QhRR/# ©r   r"   Nr)   )r   r   s   "€r   r   rŸ   Ç   s   ø€ ÷ Lñ L�tñ Lr   c           	     ó°  € V P                   ;_uu_ 4        V P                  ;_uu_ 4        \        V P                  4      p\	        V4      V P
                  8”  d*   WP
                  ) R  p\        P                  V4      V n        R R R 4       \        V P                  4       XR R7       R R R 4       R #   + '       g   i     L6; i  + '       g   i     R # ; i)N)Úindent)
r«   rª   rº   r®   r/   r§   r1   r¬   r   r¶   )r   Úthread_lists   & r   Ú_saveÚ ThreadParticipationTracker._saveÇ   sŒ   € Ø�]�]‹]Ø——“Ü" 4§=¡=Ó1�Ü�{Ó# d×&7Ñ&7Ô7Ø"-×/@Ñ/@Ð.@Ð.AÐ"B�KÜ$(§M¡M°+Ó$>�D”M÷	 ô
 ˜d×.Ñ.Ó0°+ÀdÕK÷ ‰]ß—ú÷ �]ˆ]ús#   •CªAB1	Â$CÂ1CÂ<CÃC	c                ó&   <€ V ^8„  d   QhRS[ RS[/# ©r   rÁ   r"   r#   )r   r   s   "€r   r   rŸ   Ð   s   ø€ ÷ ñ ¡3ð ©4ñ r   c                ó¾   € V P                   ;_uu_ 4        WP                  9   d    RRR4       R# RV P                  V&    RRR4       R#   + '       g   i     R# ; i)a  Record *thread_id* in memory; ``True`` when a persist is still owed.

The in-memory half stays synchronous even for :meth:`mark_async` so that
a ``thread_id in tracker`` check immediately after marking is correct --
the mention-gating logic in the adapters depends on that.
NFT©rª   r®   ©r   rÁ   s   &&r   Ú	_rememberÚ$ThreadParticipationTracker._rememberÐ   s@   € ð �Z�Z‹ZØŸM™MÔ)Ø÷ ‰Zð (,ˆD�M‰M˜)Ñ$Ø÷	 �Z�ZŠZús   •A±AÁA	c                ó$   <€ V ^8„  d   QhRS[ RR/# ©r   rÁ   r"   Nr@   )r   r   s   "€r   r   rŸ   Ý   s   ø€ ÷ ñ ™cð  dñ r   c                óX   € V P                  V4      '       d   V P                  4        R# R# )z›Mark *thread_id* as participated and persist.

Blocking: ends in ``atomic_json_write`` -> ``os.replace``.  Coroutines
must use :meth:`mark_async` instead.
N)rÏ   rÈ   rÎ   s   &&r   ÚmarkÚThreadParticipationTracker.markÝ   s!   € ð �>‰>˜)×$Ò$Ø�J‰JŽLñ %r   c                ó$   <€ V ^8„  d   QhRS[ RR/# rÒ   r@   )r   r   s   "€r   r   rŸ   æ   s   ø€ ÷ )ñ )©#ð )°$ñ )r   c              ƒ  ó~   "  € V P                  V4      '       d    \        V P                  4      G Rj  x€L
  R# R#  L5i)a�  Off-loop form of :meth:`mark`.

``_save`` ends in ``atomic_json_write`` -> ``os.replace``, whose
duration is unbounded under filesystem pressure.  Every caller of this
tracker sits on an inbound-message coroutine in the Discord and Matrix
adapters, so the rename must not be paid inline on the event loop -- it
stalls every other adapter's polling and every in-flight turn for as
long as it runs.
N)rÏ   Ú
_to_threadrÈ   rÎ   s   &&r   Ú
mark_asyncÚ%ThreadParticipationTracker.mark_asyncæ   s0   é € ð �>‰>˜)×$Ò$Ü˜TŸZ™ZÓ(×(Ò(ñ %Ù(ùs   ‚0=²;³	=c                ó&   <€ V ^8„  d   QhRS[ RS[/# rË   r#   )r   r   s   "€r   r   rŸ   ó   s   ø€ ÷ .ñ .¡cð .©dñ .r   c                ó„   € V P                   ;_uu_ 4        WP                  9   uuR R R 4       #   + '       g   i     R # ; ir   rÍ   rÎ   s   &&r   Ú__contains__Ú'ThreadParticipationTracker.__contains__ó   s!   € Ø�Z�Z‹ZØ§¡Ñ-÷ �Z�Z‹Zús   •.®?	c                ó   <€ V ^8„  d   QhRR/# rÄ   r)   )r   r   s   "€r   r   rŸ   ÷   s   ø€ ÷ "ñ "�tñ "r   c                óœ   € V P                   ;_uu_ 4        V P                  P                  4        R R R 4       R #   + '       g   i     R # ; ir   )rª   r®   rF   rG   s   &r   rF   Ú ThreadParticipationTracker.clear÷   s'   € Ø�Z�Z‹ZØ�M‰M×ÑÔ!÷ �Z�ZŠZús	   •:ºA	)r«   rª   r§   r¦   r®   N)r›   )rO   rP   rQ   rR   rS   Ú_MAX_TRACKEDr   r¶   r­   rÈ   rÏ   rÔ   rÙ   rÝ   rF   rT   rU   rV   s   @r   rš   rš   ¤   st   ø‡ € ñYð €L÷Uò U÷$Dð D÷Xð X÷Lð L÷ð ÷ð ÷)ð )÷.ð .÷"ö "r   rš   c                ó0   € V ^8„  d   QhR\         R\        /# ©r   Úchunksr"   )rº   r   )r   s   "r   r   r   ü   s   € ÷ ñ œdð ´ñ r   c              ƒ  óh  "  € ^ RI Hp V! RRR7      p\        V 4       FŒ  w  rEV! V4      G Rj  x€L
 pVP                  '       d   K)  V'       d[   \	        VP
                  \        4      '       d   \        VP
                  4      M/ pVP                  RV\        V 4      R7       Wcn         V# 	  V#  L�5i)ac  Send ``chunks`` in order through ``send_one(chunk) -> SendResult``, stopping at the first failure.

A failure after earlier chunks landed carries the ``partial_overflow`` contract that
``BasePlatformAdapter._is_partial_delivery`` reads, so no caller (send retry, plain-text
fallback, cron standalone fallback) re-sends the head the recipient already has.
)Ú
SendResultFznothing to send)ÚsuccessÚerrorNT)Úpartial_overflowÚdelivered_chunksÚtotal_chunks)	Úgateway.platforms.baserç   Ú	enumeraterè   r^   Úraw_responser1   rL   r/   )rå   Úsend_onerç   ÚresultÚ	deliveredÚchunkÚraws   &&     r   Úsend_chunksrõ   ü   sš   é € õ 2Ù Ð->Ô?€FÜ% fÖ-Ñˆ	Ù “×&ˆØ�~�~Š~ßÜ3=¸f×>QÑ>QÔSW×3XÒ3X”d˜6×.Ñ.Ô/Ð^`�Ø—
‘
¨DÀ9Ô[^Ð_eÓ[f�
ÔgØ&)Ô#ØØ€Mñ .ð €Mñ 'ùs   ‚,B2®B0¯B2ÁB2ÁA"B2c                ó0   € V ^8„  d   QhR\         R\         /# )r   Úphoner"   r@   )r   s   "r   r   r     s   € ÷ +ñ +œð +¤ñ +r   c                óÂ   € V '       g   R# \        V 4      ^8:  d-   \        V 4      ^8”  d   V R,          R,           V RR ,           # R# V R,          R,           V RR ,           # )zFRedact a phone number for logging, preserving country code and last 4.z<none>:Nr   Nz****N:Né   Néþÿÿÿéüÿÿÿ)r/   )r÷   s   &r   Úredact_phonerü     sV   € çÙÜ
ˆ5ƒz�Q„Ü25°e³*¸q´.ˆu�R�y˜6Õ! E¨"¨# JÕ.ÐLÀfÐLØ��9�vÕ  b c 
Õ*Ð*r   z0^\s*\|?\s*:?-+:?\s*(?:\|\s*:?-+:?\s*){1,}\|?\s*$c                ó0   € V ^8„  d   QhR\         R\        /# ©r   Úliner"   r#   )r   s   "r   r   r      s   € ÷ ñ ”sð œtñ r   c                ó(   € RV P                  4       9   # )z:Return True if *line* could plausibly be a table data row.Ú|)r‰   )rÿ   s   &r   Úis_table_rowr     s   € à�$—*‘*“,ÑÐr   c                óF   € V ^8„  d   QhR\         R\        \         ,          /# rþ   ©r$   rº   )r   s   "r   r   r   %  s   € ÷ !ñ !¤3ð !¬4´­9ñ !r   c                ó   € ^ RI Hp V! V 4      # )zOSplit a GFM table row into stripped cells (delegates to agent.markdown_tables).)Úsplit_table_row)Úagent.markdown_tablesr  )rÿ   r  s   & r   Úsplit_markdown_table_rowr  %  s   € å5Ù˜4Ó Ð r   c                óF   € V ^8„  d   QhR\         \        ,          R\        /# )r   Útable_blockr"   r¹   )r   s   "r   r   r   +  s   € ÷ (ñ (¤T¬#¥Yð (´3ñ (r   c           	     ó
  € \        V 4      ^8¼  d   \        V ^ ,          4      M. p\        V4      ^8  d   RP                  V 4      # \        \        V ^,          4      4      \        V4      ^,           8H  p. p\        V R,          ^R7       Fà  w  rE\        V4      pV'       d0   V'       d   V^ ,          '       d
   V^ ,          MRV 2pVR,          pM\	        R V 4       RV 24      pTpVR.\        V4      ,          ,           R\        V4       p\        W4       U	U
u. uF  w  ršV'       g	   W§8w  g   K  R	V	 R
V
 2NK  	  pp	p
VP                  RP                  RV R2.VO4      4       Kâ  	  RP                  V4      # u up
p	i )z´Render a GFM table as bold-heading + bullet groups (same alignment logic as Telegram's
renderer: without a row-label column the full row is data and the heading bullet is skipped).r‡   :r   NN)ÚstartzRow ºr(   NNc              3   ó8   "  € T F  q'       g   K  Vx € K  	  R # 5ir   r)   )r¢   Úcells   & r   r¤   Ú&_render_table_block.<locals>.<genexpr>9  s   é € Ð;©U T³dŸDšD«Uùs   ‚	�
r�   Nu   â€¢ z: z**r‘   )r/   r  Újoinrî   r}   ÚzipÚappend)r
  ÚheadersÚhas_row_label_colÚrendered_groupsÚindexÚrowÚcellsÚheadingÚ
data_cellsÚheaderrz   Úbulletss   &           r   Ú_render_table_blockr  +  sd  € ô ;>¸kÓ:JÈaÔ:OÔ& {°1¥~Ô6ÐUW€GÜ
ˆ7ƒ|�aÔØ�y‰y˜Ó%Ð%ÜÔ4°[Àµ^ÓDÓEÌÈWËÐXYÕIYÑYÐØ!#€OÜ ¨B¥°q×9‰
ˆÜ(¨Ó-ˆßß"'¨E°!¯H¬H�e˜A–h¸DÀÀ¸.ˆGØ˜r�‰JäÑ;©UÓ;¸tÀEÀ7¸^ÓLˆGØˆJØ  B 4¬#¨g«,Õ#6Õ6¸¼#¸g»,ÐGˆ
ÜADÀWÔAYô =ÑAY±°ß'¨5Ñ+;ô ,�T˜&˜  E 7Ó+ÑAYˆñ =à×Ñ˜tŸy™y¨B¨w¨i°rÐ*:Ð)E¸WÐ)EÓFÖGñ :ð �;‰;�Ó'Ð'ùó=s   ÄE?Ä4E?c                ó0   € V ^8„  d   QhR\         R\         /# ©r   r�   r"   r@   )r   s   "r   r   r   B  s   € ÷ ñ ¤3ð ¬3ñ r   c                óŒ  € RV 9  g   RV 9  d   V # V P                  R4      p. pRp^ pV\        V4      8  dþ   W,          pVP                  4       P                  R4      pW6,          pV'       gª   V'       g¢   RV9   d›   V^,           \        V4      8  d„   \        P                  W^,           ,          4      '       d\   V^,           pV\        V4      8  d#   \        W,          4      '       d   V^,          pK2  VP                  \        WV 4      4       TpKð  VP                  V4       V^,          pEK  RP                  V4      # )zURewrite GFM pipe tables into bold-heading + bullet groups; fenced code is left alone.r  Ú-r‡   Fú```)
Úsplitr/   ÚlstripÚ
startswithÚTABLE_SEPARATOR_RErƒ   r  r  r  r  )r�   ÚlinesÚoutÚin_fenceÚirÿ   Úis_fence_lineÚjs   &       r   Úconvert_table_to_bulletsr.  B  sù   € à
�$„˜# Tœ/ØˆØ�J‰J�tÓ€EØ€CØ€HØ	€AØ
Œc�%‹jŒ.Ø�xˆØŸ™›×0Ñ0°Ó7ˆØÕ!ˆßŸM¨s°d¬{¸qÀ1½uÄsÈ5ÃzÔ?QÜ&×,Ñ,¨U°qµ5­\×:Ò:Ø�A•ˆAØ”c˜%“j”.¤\°%µ(×%;Ò%;Ø�Q•’Ø�J‰JÔ*¨5°1¨:Ó6Ô7ØŠAà�J‰J�tÔØ��F‹AØ�9‰9�S‹>Ðr   Úplatform_labelÚdisplay_labelÚdefaultsÚlogger_c                óì   € V ^8„  d   QhR\         R\         R,          R\         R,          R\        \         ,          R,          R\        P                  R,          R\        \        P
                  ,          /# )r   Ú
log_prefixr/  Nr0  r1  r2  r"   )r$   rº   ÚloggingÚLoggerr„   ÚPattern)r   s   "r   r   r   [  sf   € ÷ 2Bñ 2B´ð 2BÄcÈDÅjð 2BÜ,/°$­Jð2BÜIMÌcÍÐUYÕIYð2Bä&-§n¡n°tÕ&;ð2BäGKÌBÏJÉJÕGWñ2Br   c          	     óF  aa€ T;'       g    \         oVV3R lpVeÞ   T;'       g    TpV f   . # \        V \        4      '       d   V .MT p\        V\        4      '       g*   SP	                  RSV\        V4      P                  4       . # T! V U	u. uF5  p	\        V	\        4      '       g   K  V	P                  4       '       g   K3  V	NK7  	  up	RV4      p
V
'       d   SP                  RS\        V
4      V4       V
# V f   \        T;'       g    . 4      pMÁ\        V \        4      '       d‘   V P                  4       p V'       d   \        P                  ! V4      M. p\        V\        4      '       d   TMEVP                  4        UUu. uF)  qÝP                  R4       F  qîP                  4       NK  	  K+  	  upppM\        V \        4      '       d   T MV .pR V 4        Uu. uF  qÿ'       g   K  VNK  	  ppV! VR4      # u up	i   \         d    Rp L¸i ; iu uppi u upi )	a  Compile regex wake-word/mention patterns from config or env values.

* **Config-style** (dingtalk, telegram): pass ``platform_label``. ``raw`` must be a
  list or string (else warn + ``[]``); non-string entries skipped; info log on load.
* **Wakeword-style** (photon, bluebubbles): pass ``defaults``. ``raw`` may be None
  (defaults), a string (JSON list or comma/newline separated), a list, or a scalar.
``log_prefix`` is interpolated into every log line so per-adapter output stays
byte-identical to the historical inline implementations.
c                 ó   <€ . pV  F8  p VP                  \        P                  ! V\        P                  4      4       K:  	  V#   \        P                   d%   pSP
                  ! TS.TOTNTN5!    R p?Kr  R p?ii ; ir   )r  r„   ÚcompileÚ
IGNORECASEré   Úwarning)ÚpatternsÚwarn_fmtÚ	warn_argsÚcompiledr–   ÚexcÚlogr4  s   &&*   €€r   Ú_compileÚ*compile_mention_patterns.<locals>._compilei  sr   ø€ Ø%'ˆÛˆGðLØ—‘¤§
¢
¨7´B·M±MÓ BÖCñ  ð
 ˆøô —8‘8ô LØ—’˜H jÐK°9ÐK¸gÐKÀs×KÒKûðLús   Š4AÁA=ÁA8Á8A=Nz9[%s] %s mention_patterns must be a list or string; got %sz&[%s] Invalid %s mention pattern %r: %sz$[%s] Loaded %d %s mention pattern(s)Ú,c              3   óT   "  € T F  p\        V4      P                  4       x € K   	  R # 5ir   )r$   r‰   )r¢   Úps   & r   r¤   Ú+compile_mention_patterns.<locals>.<genexpr>Œ  s   é € Ð:±¨Aœ˜Q›Ÿ™Ÿ˜³ùs   ‚&(z#[%s] Invalid mention pattern %r: %s)Úloggerr^   r$   rº   r<  ÚtyperO   r‰   Úinfor/   r½   r¾   rv   Ú
splitlinesr$  )rô   r4  r/  r0  r1  r2  rC  Údisplayr=  rG  r@  r�   Úloadedrÿ   Úpartr£   ÚtextsrB  s   &d$$$$           @r   Úcompile_mention_patternsrQ  [  sÉ  ù€ ð ×
Ð
”V€Cöð Ò!Ø×1Ð1 >ˆØŠ;ØˆIÜ& s¬C×0Ò0�C‘5°cˆÜ˜(¤D×)Ò)Ø�K‰KÐSØ" N´D¸³N×4KÑ4KôMàˆIÙ©ÓU© 1´J¸qÄ#×4FœQÈ1Ï7É7Ï9ŸQ˜Q©ÑUØDÀgóOˆçØ�H‰HÐ;¸ZÌÈXËÐX_Ô`ØˆØ
‚{Ü˜Ÿ˜ BÓ'‰Ü	�Cœ×	Ò	Ø�y‰y‹{ˆð	ß)-”T—Z’Z Ô%°2ˆFô (¨´×5Ò5‘6Ø%)§_¡_Ô%6ô<TÙ%6˜TÇ:Á:ÈcÆ?¸4�J‰JŽLÁ?‰LÑ%6ò<T‰ô % S¬$×/Ò/‘3°c°UˆÙ:±Ô:Ó@Ñ:�1»a�QˆQÑ:€EÐ@Ù�EÐ@ÓAÐAùò% Vøô ô 	ØŠFð	üó<Tùò As<   ÂH Â-H ÃH Ä<H ÅH Æ/HÇ!	HÇ/HÈHÈHc                ó0   € V ^8„  d   QhR\         R\        /# r   r#   )r   s   "r   r   r   •  s   € ÷ Mñ M¤#ð M¬$ñ Mr   c                óX   € \        R V P                  R4       4       4      ^,          ^8H  # )z?Return True when *text* ends inside an unclosed ``` code fence.c              3   óB   "  € T F  qP                  R 4      x € K  	  R# 5i)r#  N)r&  )r¢   rÿ   s   & r   r¤   Ú*text_has_unclosed_fence.<locals>.<genexpr>—  s   é € ÐCÑ2B¨$�‰˜u×%Ð%Ó2Bùs   ‚r‡   )Úsumr$  ©r�   s   &r   Útext_has_unclosed_fencerX  •  s&   € äÑC°$·*±*¸TÔ2BÓCÓCÀaÕGÈ1ÑLÐLr   c                ó0   € V ^8„  d   QhR\         R\        /# r   r#   )r   s   "r   r   r   š  s   € ÷ 7ñ 7¤3ð 7¬4ñ 7r   c                ó`   € \        V P                  4       P                  R4      R,          4      # )z=True when the last non-empty line starts and ends with ``|``.r‡   éÿÿÿÿ)Ú_is_pipe_rowÚrstripr$  rW  s   &r   Útext_ends_with_table_rowr^  š  s#   € ä˜Ÿ™›×+Ñ+¨DÓ1°"Õ5Ó6Ð6r   c                ó0   € V ^8„  d   QhR\         R\        /# r   r#   )r   s   "r   r   r   Ÿ  s   € ÷ +ñ +œð +¤ñ +r   c                ó@   € V P                  4       P                  R4      # )z<True when an atomic block is a code block (starts with ```).r#  )r%  r&  rW  s   &r   Úis_fence_atomra  Ÿ  s   € à�;‰;‹=×#Ñ# EÓ*Ð*r   c                ó0   € V ^8„  d   QhR\         R\        /# rþ   r#   )r   s   "r   r   r   ¤  s   € ÷ ?ñ ?”sð ?œtñ ?r   c                 óv   € V P                  4       pVP                  R 4      ;'       d    VP                  R 4      # )r  )r‰   r&  Úendswith)rÿ   Ústrippeds   & r   r\  r\  ¤  s1   € Ø�z‰z‹|€HØ×Ñ˜sÓ#×>Ð>¨×(9Ñ(9¸#Ó(>Ð>r   c                ó0   € V ^8„  d   QhR\         R\        /# r   r#   )r   s   "r   r   r   ©  s   € ÷ -ñ -œð -¤ñ -r   c                óD   € \        V P                  R4      ^ ,          4      # )z?True when an atomic block is a table (first line is ``|...|``).r‡   )r\  r$  rW  s   &r   Úis_table_atomrh  ©  s   € ä˜Ÿ
™
 4Ó(¨Õ+Ó,Ð,r   u   [ã€‚ï¼�ï¼Ÿ.!?]\nc                ó8   € V\         J d   V# ^ RIHp V! WV4      # )z¢Code-point count of the longest prefix of *text* within *budget* ``len_fn`` units
(callers guarantee ``len_fn(text) > budget``, so plain ``len`` needs no search).)Ú_custom_unit_to_cp)r/   rí   rj  )r�   ÚbudgetÚlen_fnrj  s   &&& r   Ú
_cp_budgetrm  ±  s    € ð ”ƒ}ØˆÝ9Ù˜d¨FÓ3Ð3r   c                ó°  € T;'       g    \         pV! V 4      V8:  d   V R3# V R\        WV4       pVP                  R4      p\        P	                  V4       Uu. uF  qfP                  4       NK  	  ppV^ 8”  d
   V^,           MV'       d
   VR,          M^ pV'       g-   VP                  R4      pV^ 8”  d
   V^,           M
\        V4      pV RV WR 3# u upi )u=  Split at the nearest paragraph boundary within *max_chars*; return (head, tail).

Priority: blank line â†’ newline after sentence-ending punctuation (CJK/ASCII)
â†’ last newline â†’ forced split at the window boundary. ``head + tail == text``
always holds. *len_fn* measures in custom units (e.g. UTF-16 code units).
r�   Nr‘   r‡   r[  )r/   rm  ÚrfindÚ_SENTENCE_END_NEWLINE_REÚfinditerÚend)	r�   Ú	max_charsrl  Ú_lenÚwindowÚposÚmÚsentence_endsÚcuts	   &&&      r   Úsplit_at_paragraph_boundaryrz  º  sÆ   € ð �=ˆ=”S€DÙˆDƒz�YÔØ�RˆxˆØÐ4”:˜d¨tÓ4Ð5€FØ
�,‰,�vÓ
€CÜ&>×&GÑ&GÈÔ&OÓPÑ&O —U‘U–WÑ&O€MÐPØ˜1”Wˆ#�Ž'¿ =°Ö#4È1€CßØ�l‰l˜4Ó ˆØ˜qœˆc�AŽg¤c¨&£kˆØ��ˆ:�t˜D�zÐ!Ð!ùò Qs   ÁCc                óF   € V ^8„  d   QhR\         R\        \         ,          /# r   r  )r   s   "r   r   r   Î  s   € ÷  ñ  œsð  ¤t¬C¥yñ  r   c                ó  aa€ . o. oRpR VV3R llpV P                  R4       FÑ  pV'       d6   SP                  V4       VP                  R4      '       d   RpV! 4        K>  K@  VP                  R4      '       d   V! 4        RpSP                  V4       Ks  VP                  4       R8X  d
   V! 4        K‘  S'       d(   \	        SR,          4      \	        V4      8w  d   V! 4        SP                  V4       KÓ  	  V! 4        S# )	zŽSplit markdown into indivisible atoms: fenced code blocks, tables
(consecutive ``|...|`` lines) and paragraphs. Blank lines belong to no atom.Fc                ó   € V ^8„  d   QhRR/# rÄ   r)   )r   s   "r   r   Ú*split_markdown_atoms.<locals>.__annotate__Õ  s   € ÷ "ñ "˜Dñ "r   c                  ó¬   <€ S'       dK   R P                  S4      p V P                  4       '       d   SP                  V 4       SP                  4        R# R# )r‡   N)r  r‰   r  rF   )ÚatomÚatomsÚcurrent_liness    €€r   Ú_flush_currentÚ,split_markdown_atoms.<locals>._flush_currentÕ  s<   ø€ ßØ—9‘9˜]Ó+ˆDØ�z‰z�|Š|Ø—‘˜TÔ"Ø×ÑÖ!ñ	 r   r‡   r#  Tr�   r[  )r$  r  r&  r‰   r\  )r�   r*  rƒ  rÿ   r�  r‚  s   &   @@r   Úsplit_markdown_atomsr…  Î  sÞ   ù€ ð €EØ!€MØ€H÷"ñ "ð —
‘
˜4Ö ˆßØ× Ñ  Ô&Ø�‰˜u×%Ò%Ø �ÙÖ ñ &ð �_‰_˜U×#Ò#ÙÔØˆHØ× Ñ  Ö&Ø�Z‰Z‹\˜RÔÙÖ÷ ¤¨m¸BÕ.?Ó!@ÄLÐQUÓDVÔ!VÙÔ Ø× Ñ  Ö&ñ! !ñ" ÔØ€Lr   c                ó<   € V ^8„  d   QhR\         R\         R\         /# )r   Ú
prev_chunkÚ
next_chunkr"   r@   )r   s   "r   r   r   ñ  s!   € ÷ ñ ¤cð ´sð ¼sñ r   c                ó*  € V P                  4       pVP                  4       pVP                  R4      '       g   VP                  R4      '       d   R# \	        V 4      '       d2   V'       d*   \        VP                  R4      ^ ,          4      '       d   R# R# )zV``'\n'`` when the boundary sits at a code fence or a continued table, else ``'\n\n'``.r#  r‡   r‘   )r]  r%  rd  r&  r^  r\  r$  )r‡  rˆ  Úprev_trimmedÚnext_trimmeds   &&  r   Úinfer_block_separatorrŒ  ñ  sq   € à×$Ñ$Ó&€LØ×$Ñ$Ó&€LØ×Ñ˜U×#Ò# |×'>Ñ'>¸u×'EÒ'EÙÜ 
×+Ò+·ÄÈl×N`ÑN`ÐaeÓNfÐghÕNi×AjÒAjÙÙr   c                ó\   € V ^8„  d   QhR\         \        ,          R\         \        ,          /# rä   r¹   )r   s   "r   r   r   ü  s"   € ÷ ñ ¤4¬¥9ð ´´cµñ r   c                óD  € . p^ pV\        V 4      8  dŒ   W,          p\        V4      '       dW   V^,           \        V 4      8  d@   V\        W0V^,           ,          4      ,           W^,           ,          ,           pV^,          pKg  VP                  V4       V^,          pK›  V# )zšRejoin chunks truncated mid-fence: while chunk *i* has an unclosed fence
and a successor exists, merge the successor in via :func:`infer_block_separator`.)r/   rX  rŒ  r  )rå   rñ   r+  ra   s   &   r   Úmerge_streaming_fencesr�  ü  s„   € ð €FØ	€AØ
Œc�&‹kŒ/Ø•)ˆÜ% g×.Ò.°1°qµ5¼3¸v»;Ô3FØÔ 5°gÀaÈ!Åe½}Ó MÕMÐPVÐ[\ÕW\ÕP]Õ]ˆGØ��FŠAØ�‰�gÔØ	ˆQ�ŠØ€Mr   c                ó\   € V ^8„  d   QhR\         \        ,          R\         \        ,          /# rä   r¹   )r   s   "r   r   r     s"   € ÷ ñ ¬¬c­ð ´t¼Cµyñ r   c                óð   € \        V 4      ^8:  d   V # . pRpV  FY  pVe	   RV RV 2MTp\        Y2RJT;'       g    R4      w  rVV'       d   TMRpTP                  V'       d
   VR,           MT4       K[  	  V# )z‘Close orphaned ``` fences at each chunk boundary and reopen (with the
original language tag) on the next, so every chunk is fence-balanced alone.Nr#  r‡   r�   z
```)r/   Úfence_state_afterr  )rå   r)  Ú
carry_langró   ÚbodyÚin_codeÚlangs   &      r   Úbalance_fences_across_chunksr—    s‚   € ô ˆ6ƒ{�aÔØˆØ€CØ€JÛˆØ.8Ò.D��Z�L  5 'Ñ*È%ˆÜ)¨%À4Ð1GÈ×IYÐIYÐWYÓZ‰ˆß$‘T¨$ˆ
Ø�
‰
§W�4˜'–>°$Ö7ñ	 ð
 €Jr   c          
      ój   € V ^8„  d   QhR\         R\        R\         R\        \        \         3,          /# )r   r�   r•  r–  r"   )r$   r%   Útuple)r   s   "r   r   r     s4   € ÷ ñ œCð ¬$ð ¼cð Ì5ÔQUÔWZÐQZÕK[ñ r   c                óú   € V P                  R4       Fd  pVP                  4       pVP                  R4      '       g   K,  VR,          P                  4       pV'       d   RMRV'       d
   V^ ,          MR3w  rKf  	  W3# )zSWalk ``text`` line by line toggling on ``` lines; return the final (in_code, lang).r‡   r#  :é   NNr�   T©Fr�   )r$  r‰   r&  )r�   r•  r–  rÿ   re  Útags   &&&   r   r’  r’    sh   € à—
‘
˜4Ö ˆØ—:‘:“<ˆØ×Ñ˜u×%Ô%Ø˜2•,×$Ñ$Ó&ˆCß+2™K¸Ï¸sÀ1¾vÐRTÐ8U‰MˆG‘Tñ	 !ð
 ˆ=Ðr   c                ól  € T;'       g    \         p. pRpV  F€  pV'       g   TMV V V 2p	V! V	4      V8:  d   T	pK&  V'       d   VP                  V4       RpV! V4      V8:  d   TpKR  Ve   VP                  V! V4      4       Ko  VP                  V4       K‚  	  V'       d   VP                  V4       V# )z«Greedily pack *blocks* (joined with *sep*) into chunks of at most *max_length*; an
oversized block goes through *overflow(block)* (-> list of chunks) if given, else as-is.r�   )r/   r  Úextend)
ÚblocksÚ
max_lengthrl  ÚsepÚoverflowrt  Úpackedra   ÚblockÚ	candidates
   &&&&&     r   Úgreedy_pack_blocksr§  $  sª   € ð �=ˆ=”S€DØ€FØ€GÛˆß!(‘E°°	¸#¸¸u¸gÐ.Fˆ	Ù�	‹?˜jÔ(ØˆGÙßØ�M‰M˜'Ô"ØˆGÙ�‹;˜*Ô$ØŠGØÒ!Ø�M‰M™( 5›/Ö*à�M‰M˜%Ö ñ ÷ Ø�‰�gÔØ€Mr   Úprefer_paragraphsTÚbalance_fencesc               óž   € V '       g   . # V'       d   \        WV4      pM\        YT;'       g    \        4      pV'       d   \        V4      # T# )a)  Split markdown into chunks of at most *limit*, respecting fences.

``prefer_paragraphs=True`` (yuanbao-derived): atoms (fences, tables, paragraphs) are
greedily merged, oversized non-atomic chunks split at paragraph boundaries, small
neighbours re-merged; a single atom larger than *limit* is emitted oversize, not broken.
``prefer_paragraphs=False`` (stream_consumer-derived): newline-preferred hard splitting
with headroom reserved for fence markers. ``balance_fences=True`` closes/reopens fences
at chunk boundaries so each chunk renders standalone.
)Ú_chunk_markdown_paragraphsÚ_chunk_newline_preferredr/   r—  )r�   Úlimitrl  r¨  r©  rå   s   &&&$$ r   Úsplit_text_fence_awarer®  =  s@   € ÷ Øˆ	ßÜ+¨D¸Ó@‰ä)¨$°v·}°}ÄÓEˆß3AÔ'¨Ó/ÐMÀvÐMr   c                óÌ  € T;'       g    \         pV! V 4      V8:  d   V .# . p\        4       p. p^ p\        V 4       FÕ  pV! V4      p	V'       d   ^M^ p
Wz,           V	,           V8”  d.   V'       d&   VP                  RP	                  V4      4       . ^ ^ r§pV'       gV   W‘8”  dP   \        V4      '       g   \        V4      '       d.   VP                  \        V4      4       VP                  V4       Kµ  VP                  V4       WzV	,           ,          pK×  	  V'       d!   VP                  RP	                  V4      4       . p\        V4       F¢  w  rÍV! V4      V8:  g   WÅ9   g   \        V4      '       d   VP                  V4       K<  TpV! V4      V8”  d=   \        WáVR7      w  rþV'       g	   VRV WáR rïV'       g   K6  VP                  V4       KI  V'       g   K‘  VP                  V4       K¤  	  VR,          pVR,           F?  pVR,          R,           V,           pV! V4      V8:  d   VVR&   K.  VP                  V4       KA  	  V Uu. uF  pV'       g   K  VNK  	  up# u upi )zCYuanbao-derived paragraph/atom chunking pipeline (see module docs).r‘   )rl  N:Nr(   Nr  r[  )r/   Úsetr…  r  r  ra  rh  Úaddrî   rX  rz  )r�   rs  rl  rt  rå   Úindivisible_setÚcurrent_partsÚcurrent_lenr€  Úatom_lenÚsep_lenrñ   Úidxró   Ú	remainingÚheadÚmergedÚcombinedÚcs   &&&                r   r«  r«  Q  s  € à�=ˆ=”S€DÙˆDƒz�YÔØˆvˆà€FÜ #£€OØ!€MØ€KÜ$ TÖ*ˆÙ˜“:ˆß$‘!¨!ˆØÕ  8Õ+¨iÔ7¿MØ�M‰M˜&Ÿ+™+ mÓ4Ô5Ø24°a¸¨ˆMß (Ô"6Ü" 4×(Ò(¬M¸$×,?Ò,?Ø×Ñ¤ F£Ô,Ø�M‰M˜$ÔÙØ×Ñ˜TÔ"Ø Õ)Õ)Šñ +÷ Ø�‰�f—k‘k -Ó0Ô1à€FÜ Ö'‰
ˆÙ�‹;˜)Ô# sÔ'=ÔAXÐY^×A_ÒA_Ø�M‰M˜%Ô ÙØˆ	Ù�9‹o 	Ô)Ü9¸)ÐW]Ô^‰OˆDßØ"+¨J¨YÐ"7¸À:Ð9N�iß‰tØ—‘˜dÖ#ß‰9Ø�M‰M˜)Ö$ñ (ð ˜r�
€FØ˜—�ˆØ˜"•: Õ&¨Õ.ˆÙ�‹>˜YÔ&Ø!ˆF�2‹Jà�M‰M˜%Ö ñ ñ Ó#‘v�!¤�AˆA‘vÑ#Ð#ùÒ#s   É	
I!ÉI!c                óp  € V! V 4      V8:  d   V .# RV 9   d   \        V^,
          V^,          ^4      MTp. pT pV! V4      V8”  dX   \        WSV4      pVP                  R^ V4      pWv^,          8  d   TpVP                  VRV 4       WWR P	                  R4      pKd  V'       d   VP                  V4       V# )zCStream-consumer-derived newline-preferred splitting (no balancing).r#  r‡   N)Úmaxrm  ro  r  r%  )r�   r­  rl  Úsplit_limitrå   r¸  rk  Úsplit_ats   &&&     r   r¬  r¬  „  s³   € áˆdƒ|�uÔØˆvˆà49¸T´M”#�e˜b•j %¨1¥*¨aÔ0Àu€KØ€FØ€IÙ
�Ó
˜kÔ
)Ü˜I°FÓ;ˆØ—?‘? 4¨¨FÓ3ˆØ •kÔ!ØˆHØ�‰�i 	 Ð*Ô+Ø˜iÐ(×/Ñ/°Ó5Š	ßØ�‰�iÔ Ø€Mr   Ú___hidden___c                ó$   € V ^8„  d   QhR\         /# r±   )r%   )r   s   "r   r   r      s   € ÷ Mñ M¬dñ Mr   c                óÔ   €  V P                   P                  p\        V\        4      '       d   V\
        ,          '       d   R# \        V RR4      \        8H  #   \         d    Rp LNi ; i)u®  True when a discord.py channel object is an obfuscated placeholder.

Skip these wherever guild channels are enumerated (channel directory, message
backfill): history reads and sends always fail with a permission error. Flag
first; the sentinel name is the fallback for discord.py builds that don't
expose the flag (a visible channel literally named ``___hidden___`` is then
also skipped â€” deliberate bias toward hiding). #90154
NTr_   )Úflagsrz   ÚAttributeErrorr^   r   ÚDISCORD_CHANNEL_OBFUSCATED_FLAGr]   ÚDISCORD_OBFUSCATED_CHANNEL_NAME)ÚchannelÚ
flag_values   & r   Úis_discord_channel_obfuscatedrÊ     s^   € ðØ—]‘]×(Ñ(ˆ
ô �*œc×"Ò" zÔ4S×'SÔ'SÙÜ�7˜F DÓ)Ô-LÑLÐLøô	 ô ØŠ
ðús   ‚A ÁA'Á&A'c                ó0   € V ^8„  d   QhR\         R\         /# )r   Úkwargsr"   rZ   )r   s   "r   r   r   ²  s   € ÷ Fñ F¤3ð F¬3ñ Fr   c                 ó<  € ^ RI Hp ^ RIHp ^ RIHp \        V P                  RR4      ;'       g    / 4      pV.VP                  RR4      OVR&   V P                  RR4       V P                  R	R
4       RV 9  d   V! 4       V R&   MV R,          f   V R V! RRV/V B # )a»  ``httpx.AsyncClient`` for a platform adapter: connect-time SSRF validation
(``tools.url_safety.create_ssrf_safe_async_client``), every redirect hop re-checked
(``gateway.platforms.base.ssrf_redirect_guard``, run before any caller ``response`` hooks) and the
shared keepalive pool limits (``platform_httpx_limits()``; pass ``limits=None`` for httpx's
defaults). Defaults ``timeout=30.0`` and ``follow_redirects=True``; other kwargs go to httpx.)Úplatform_httpx_limits)Ússrf_redirect_guard)Úcreate_ssrf_safe_async_clientÚevent_hooksNÚresponseÚtimeoutg      >@Úfollow_redirectsTÚlimitsr)   )
Ú%gateway.platforms._http_client_limitsrÎ  rí   rÏ  Útools.url_safetyrÐ  r1   rB   r;   Ú
setdefault)rÌ  rÎ  rÏ  rÐ  Úhookss   ,    r   Úplatform_http_clientrÚ  ²  s¤   € õ LÝ:Ý>Ü�—‘˜M¨4Ó0×6Ð6°BÓ7€EØ,ÐI¨u¯y©y¸ÀRÓ/HÐI€Eˆ*ÑØ
×Ñ�i Ô&Ø
×ÑÐ(¨$Ô/Ø�vÔÙ0Ó2ˆˆxÒØ	�Õ	Ò	!Ø�8ÐÙ(ÑE°UÐE¸fÑEÐEr   r   rœ  )Nr‘   Ni   )DrS   rm   rs   r½   r5  r„   r¨   r.   Úpathlibr   Útypingr   r   r   Úgateway.platforms.eventr   Úutilsr   Ú	getLoggerrO   rI  r
   rb   rj   Ú	to_threadrØ   rw   r   r:  ÚDOTALLÚ	MULTILINEr’   r”   r;  rŠ   r•   rŒ   r˜   rš   rõ   rü   r'  r  r  r  r.  rQ  rX  r^  ra  r\  rh  rp  rm  rz  r…  rŒ  r�  r—  r’  r§  r®  r«  r¬  rÆ  rÇ  rÊ  rÚ  r)   r   r   Ú<module>rã     sN  ðñ3ó Û Û Û Û 	Û Û Ý ß 0Ñ 0Ý 0Ý #à	×	Ò	˜8Ó	$€÷.hñ .hõb%õð ×Ñ€
õ	õ%ð ‡Z‚ZÐ  "§)¡)Ó,¨eÐ4Ø‡Z‚Z�˜bŸi™iÓ(¨%Ð0Ø‡Z‚ZÐ3°R·Y±YÓ?ÀÐGØ‡Z‚ZÐ1°2·9±9Ó=¸uÐEØ‡Z‚ZÐ(Ó)¨2Ð.Ø‡Z‚Z�
Ó˜UÐ#Ø‡Z‚Z�˜rŸ|™|Ó,¨bÐ1ð€ð �jŠjÐ4Ó5€Ø—*’*˜\¨2¯=©=Ó9€Ø—j’j Ó+Ð õ?ð	9¸5÷ 	9÷U"ñ U"õpõ(+ð —Z’ZÐ SÓTÐ õõ
!õ(õ.ð22BÐSWð 2BØ9=ð2BØ\`ð2Bà>B÷2BõtMõ
7õ
+õ
?õ
-ð
 Ÿ:š:Ð&9Ó:Ð ò4ô"õ( õFõõ÷ôñ2NÈ$ð NØ*/õNô(0$òfð0 #*Ð Ø"0Ð õM÷$Fr   