Ë
    âß²j� ã                  ó²  — d Z ddlmZ ddlZddlZddlZddlZddlZddl	Z	ddl
Z
ddlZddlZddlmZ ddlmZmZmZ  ej&                  d«      Z eh d£«      Z edh«      Zi d	d
“dd“dd“dd“dd“dd“dd“dd“dd“dd“dd“dd “d!d"“d#d$“d%d&“d'd(“Zd$d)iZd„d*„Zd…d+„Zd†d‡d,„Z	 	 	 	 dˆd-„Zd.d/d/d0d1œZdd2œ	 	 	 	 	 	 	 	 	 d‰d3„ZdŠd4„Z d‹d5„Z!dŒd6„Z"d�d7„Z#	 	 dŽd8d9œ	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 d�d:„Z$d;d;d;d<œZ%d�d=„Z&dd8d>œ	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 d‘d?„Z'	 d’	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 d“d@„Z(dddAœ	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 d”dB„Z)dŒdC„Z*d•dD„Z+d–dE„Z,d•dF„Z-d—dG„Z.d˜d8dHœd™dI„Z/d•dJ„Z0d•dK„Z1dšdL„Z2dM„ Z3d›dN„Z4dœdO„Z5d�dP„Z6dždQ„Z7d†dŸdR„Z8d8dSœ	 	 	 	 	 	 	 d dT„Z9d¡dU„Z:d¡dV„Z;dWZ<dXZ=dYZ>d¢dZ„Z?d£d[„Z@dd8d\œ	 	 	 d¤d]„ZAd£d^„ZB ed_h«      ZCd`ZDdaZEd¥db„ZFd¦dc„ZGd§dd„ZHd8deœd¨df„ZId8deœd©dg„ZJd…dh„ZK eh di£«      ZL eh dj£«      ZM	 d†	 	 	 	 	 	 	 	 	 dªdk„ZNd†d«dl„ZO	 d¬	 	 	 	 	 d­dm„ZPd®dn„ZQd¯do„ZRd°dp„ZSe G dq„ dr«      «       ZTd±ds„ZUd²dt„ZV	 	 	 	 	 	 d³du„ZWd–dv„ZXd´dw„ZY	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 dµdx„ZZ	 	 	 	 	 	 	 	 	 	 d¶dy„Z[d·dz„Z\	 	 	 	 	 	 	 	 	 	 	 	 	 	 d¸d{„Z]	 	 	 	 	 	 	 	 d¹d|„Z^	 	 	 	 	 	 	 	 	 	 	 	 dºd}„Z_	 	 	 	 	 	 	 	 	 	 	 	 	 	 d»d~„Z`d¼d„Za	 dŽd8deœ	 	 	 	 	 	 	 d½d€„Zbdd�lcmdZe dd‚lcmfZg ddƒlcmhZi y)¾aÖ  Cron delivery: target resolution (origin/home/explicit/bot-chat), transcript mirroring and
session seeding, live-adapter / relay / standalone send lanes, and ``_deliver_result``.

Split out of ``cron.scheduler``. Import names from this module directly (``cron.scheduler`` only
imports the few it calls itself). Origin-resident helpers and sibling split modules are reached
late-bound (``_sched`` / module refs at the bottom) so monkeypatching the defining module works.
é    )ÚannotationsN)Ú	dataclass)ÚAnyÚListÚOptionalzcron.scheduler>   ÚsmsÚemailÚqqbotÚslackÚwecomÚfeishuÚmatrixÚsignalÚweixinÚdiscordÚwebhookÚyuanbaoÚdingtalkÚtelegramÚwhatsappÚ
mattermostÚbluebubblesÚhomeassistantÚwecom_callbackÚ
api_serverr   ÚMATRIX_HOME_ROOMr   ÚTELEGRAM_HOME_CHANNELr   ÚDISCORD_HOME_CHANNELr   ÚSLACK_HOME_CHANNELr   ÚSIGNAL_HOME_CHANNELr   ÚMATTERMOST_HOME_CHANNELr   ÚSMS_HOME_CHANNELr	   ÚEMAIL_HOME_ADDRESSr   ÚDINGTALK_HOME_CHANNELr   ÚFEISHU_HOME_CHANNELr   ÚWECOM_HOME_CHANNELr   ÚWEIXIN_HOME_CHANNELr   ÚBLUEBUBBLES_HOME_CHANNELr
   ÚQQBOT_HOME_CHANNELr   ÚWHATSAPP_HOME_CHANNELÚwhatsapp_cloudÚWHATSAPP_CLOUD_HOME_CHANNELÚQQ_HOME_CHANNELc                ó²  — t        j                  t        «      5  t        | dd«      xs i }|j	                  t        |xs d«      j                  «       «      }t        |t        «      r|j	                  d«      nd}|€|j	                  d«      }|�4t        |«      j                  «       j                  «       dk(  r
	 ddd«       yddd«       y# 1 sw Y   yxY w)u  Return ``"in_channel"`` or ``"thread"`` (default) for a platform config.

    Native: flat ``platforms.<p>.extra.cron_continuable_surface``. Relay-fronted:
    ``platforms.relay.extra.<logical>.cron_continuable_surface`` (same sub-block as the relay's
    Slack knobs); the sub-block wins and is scoped to its logical platform. Unlike
    _relay_slack_extra, a sub-block that omits the knob falls back to the flat key (deliberate â€”
    the flat key must keep working), so a flat value applies to EVERY platform the relay fronts.
    ÚextraNÚ Úcron_continuable_surfaceÚ
in_channelÚthread)
Ú
contextlibÚsuppressÚ	ExceptionÚgetattrÚgetÚstrÚlowerÚ
isinstanceÚdictÚstrip)ÚpconfigÚlogical_platform_namer/   ÚsubÚraws        ú</home/ubuntu/.hermes/hermes-agent/cron/scheduler_delivery.pyÚ_resolve_cron_surface_moderC   ?   s½   € ô 
×	Ñ	œYÓ	'ñ  Ü˜ ¨$Ó/Ò5°2ˆØ�i‰iœÐ1Ò7°RÓ8×>Ñ>Ó@ÓAˆÜ5?ÀÄTÔ5Jˆc�g‰gÐ0Ô1ÐPTˆØˆ;Ø—)‘)Ð6Ó7ˆCØˆ?œs 3›xŸ~™~Ó/×5Ñ5Ó7¸<ÒGØ÷ ÷  ð  ð ÷ ð ús   šB!CÃCc                óÔ   — | j                  d«      }t        |t        «      rG|j                  d«      r6|j                  d«      r%t        |d   «      j	                  «       t
        v ry|S y)u  Extract origin info from a job. Non-dict origins (provenance strings, hand-edited
    jobs.json) are treated as missing â€” otherwise every fire crashed on ``origin.get``.

    Without this guard, a job tagged with e.g. ``"combined-digest-replaces-x-and-y"`` crashed every fire
    attempt with ``'str' object has no attribute 'get'`` â€” ``mark_job_run`` recorded the failure, but the
    next tick re-loaded the same poisoned origin and crashed identically until the field was patched
    manually (#18722).
    ÚoriginÚplatformÚchat_idN)r8   r;   r<   r9   r:   Ú_NON_PUSH_ORIGIN_PLATFORMS)ÚjobrE   s     rB   Ú_resolve_originrJ   S   s[   € ð �W‰W�XÓ€FÜ�&œ$Ô F§J¡J¨zÔ$:¸v¿z¹zÈ)Ô?Tô ˆv�jÑ!Ó"×(Ñ(Ó*Ô.HÑHØØˆØó    c                óú   — | j                  d«      }t        |t        «      r|S 	 |€t        j                  «       xs i }t        |j                  di «      xs i j                  dd«      «      S # t
        $ r Y yw xY w)uÊ  Whether a cron delivery is also mirrored into the target chat's session transcript.

    Default OFF. Precedence: per-job ``attach_to_session`` (bool) â†’ global
    ``cron.mirror_delivery`` â†’ False. CARVE-OUT: the ``in_channel`` surface seeds its session
    independently of this knob (the seed IS that feature) â€” this governs only the thread-surface
    mirror. ``mirror_to_session`` runs at a turn boundary, so it is alternation- and cache-safe.
    Úattach_to_sessionÚcronÚmirror_deliveryF)r8   r;   ÚboolÚ_schedÚload_configr6   )rI   ÚcfgÚper_jobs      rB   Ú_cron_mirror_delivery_enabledrU   g   sz   € ð �g‰gÐ)Ó*€GÜ�'œ4Ô ØˆðØˆ;Ü×$Ñ$Ó&Ò,¨"ˆCÜ�S—W‘W˜V RÓ(Ò.¨B×3Ñ3Ð4EÀuÓMÓNÐNøÜò Ùðús   ¥AA. Á.	A:Á9A:c                ó@  — | rjt        | j                  dd«      «      j                  «       t        |«      j                  «       k7  s't        | j                  dd«      «      t        |«      k7  ry| j                  d«      }|du xs t        |«      t        |xs d«      k(  S )uð   True when a delivery target is the job's own origin conversation. A pinned origin
    thread_id must match â€” a target without it is a different lane. Mirror eligibility for
    non-origin targets is decided by ``_target_mirror_eligible``.rF   r0   rG   FÚ	thread_idN)r9   r8   r:   )rE   Úplatform_namerG   rW   Úorigin_threads        rB   Ú_target_matches_originrZ   z   s†   € ñ Üˆv�z‰z˜* bÓ)Ó*×0Ñ0Ó2´c¸-Ó6H×6NÑ6NÓ6PÒPÜˆv�z‰z˜) RÓ(Ó)¬S°«\Ò9àØ—J‘J˜{Ó+€MØ˜DÐ ÒN¤C¨Ó$6¼#¸iºoÈ2Ó:NÑ$NÐNrK   é   é   é   )rE   Úorigin_fallbackÚhomeÚexplicit)Úorigin_matchc               ó\  — |€Lt        | «      xs i }t        ||j                  dd«      |j                  dd«      |j                  d«      «      }|ry|j                  d«      }|dv r.| j                  d«      }t        |t        «      r|S t	        |«      S |d	k(  r| j                  d«      du S y
)už  Whether a resolved delivery target may receive the transcript mirror. Origin targets:
    always. ``origin_fallback`` (deliver=origin with no captured origin â†’ home channel, standing
    in for the primary conversation) and ``home`` (user-written bare-platform token, e.g.
    ``deliver: slack`` â€” deliberately addresses that platform's home channel): same flags as a
    true origin. ``explicit`` ``platform:chat_id``: ONLY with per-job ``attach_to_session: true``
    â€” the global flag must never write transcripts into arbitrary explicitly-addressed chats.
    Untagged broadcast expansions (``all``) are never eligible. ``origin_match`` may be
    precomputed.rF   r0   rG   rW   TÚ_resolved_from)r^   r_   rM   r`   F)rJ   rZ   r8   r;   rP   )rI   ÚtargetÚglobal_mirrorra   rE   Úresolved_fromrT   s          rB   Ú_target_mirror_eligiblerg   Ž   sµ   € ð ÐÜ  Ó%Ò+¨ˆÜ-Ø�F—J‘J˜z¨2Ó.°·
±
¸9ÀbÓ0IÈ6Ï:É:ÐVaÓKbódˆáØØ—J‘JÐ/Ó0€MØÐ3Ñ3ð —'‘'Ð-Ó.ˆÜ$ W¬dÔ3ˆwÐL¼¸mÓ9LÐLØ˜
Ò"Ø�w‰wÐ*Ó+¨tÐ3Ð3ØrK   c                ó    — t        | xs |«      S )u  Whether the flat in_channel seed may run. Group keys are user-isolated
    (``â€¦:group:<chat_id>:<user_id>``): seeding without a real user_id creates an orphan session no
    reply resolves to â€” worse than no seed. DM keys omit user_id, so DMs are always seedable.)rP   ©Úis_dmÚuser_ids     rB   Ú_inchannel_seed_allowedrl   ©   s   € ô �Ò ˜Ó!Ð!rK   c                ó†   — | s| S 	 ddl m}  || d¬«      S # t        $ r!}t        j	                  d||«       Y d}~yd}~ww xY w)u‰  Fail-closed secret redaction for anything a cron job emits outward.

    Every outward lane â€” chat message, session mirror, bot-chat turn â€” must apply the same policy,
    so the policy lives in one place. ``force=True`` because this is a safety boundary, not
    logging: the ``security.redact_secrets`` preference governs how much is scrubbed from the
    user's own logs and must not be able to turn scrubbing off on the way out to a chat (same
    reasoning as ``tools/delegation_live_log.py``). Empty input is returned as-is; any failure
    inside the redactor replaces the payload entirely rather than letting an unscanned value out.
    r   ©Úredact_sensitive_textT)Úforcez)Failed to redact secrets from cron %s: %sNz[REDACTED - redaction failed])Úagent.redactro   r6   ÚloggerÚwarning)ÚtextÚwhatro   Úes       rB   Ú_redact_cron_payloadrw   °   sE   € ñ Øˆð/Ý6Ù$ T°Ô6Ð6øÜò /Ü�‰ÐBÀDÈ!ÔLÜ.ûð/ús   † –	A Ÿ;»A c                ó`   — t        | j                  d«      xs | j                  dd«      d«      S )u  Job name/id as it appears in outward-facing text. The mirror sinks and the thread title
    splice the job *name* around the redacted payload, and the name is user-controlled config â€” a
    name embedding a credential would re-leak it next to the scrubbed body.ÚnameÚidrN   újob name)rw   r8   )rI   s    rB   Ú_cron_display_namer|   Ä   s)   € ô   §¡¨£Ò H°3·7±7¸4ÀÓ3HÈ*ÓUÐUrK   c                ó$   — dt        | «      › d|› �S )Nz[Cron delivery: z]
)r|   )rI   rt   s     rB   Ú_cron_mirror_messager~   Ë   s   € ØÔ0°Ó5Ð6°c¸$¸Ð@Ð@rK   F©Úenabledc          	     ó®  — |sy|xs dj                  «       }|sy	 ddlm}  ||t        |«      t	        | |«      d||d¬«      }	|	r)t
        j                  d| j                  d	d
«      ||«       yt
        j                  d| j                  d	d
«      ||«       y# t        $ r3}
t
        j                  d| j                  d	d
«      |||
«       Y d}
~
yd}
~
ww xY w)uœ  Best-effort mirror of a cron delivery into the origin chat's session. No-op unless
    ``enabled`` (caller resolves it, scoped to the origin target). Rides the same
    ``mirror_to_session`` path as ``send_message``, passing ``user_id`` so user-isolated group
    chats resolve to the scheduling member. All failures swallowed â€” a successful delivery must
    never be reported failed because the mirror broke.Nr0   r   ©Úmirror_to_sessionrN   Úuser)Úsource_labelrW   rk   Úrolez9Job '%s': mirrored delivery into %s:%s session transcriptrz   ú?uX   Job '%s': delivery mirror skipped for %s:%s (no matching gateway session â€” cold start)z.Job '%s': delivery mirror failed for %s:%s: %s)
r=   Úgateway.mirrorrƒ   r9   r~   rr   Úinfor8   Údebugr6   )rI   rX   rG   Úmirror_textrW   rk   r€   rt   rƒ   Úokrv   s              rB   Ú_maybe_mirror_cron_deliveryr�   Ï   sÚ   € ñ ØØÒ˜2×$Ñ$Ó&€DÙØð
Ý4ñ Øœ3˜w›<Ô)=¸cÀ4Ó)HØ¨9¸gÈFôTˆñ Ü�K‰KØKØ—‘˜˜cÓ" M°7õ<ô �L‰Lð?à—‘˜˜cÓ" M°7õ<øô ò 
Ü�‰Ø<¸c¿g¹gÀdÈCÓ>PÐR_Ø�Q÷	
ñ 	
ûð
ús   œAB Á/(B Â	CÂ!)CÃCÚgroup)r   r   r   c           
     ór  — t        |dd«      }t        |«      r|€ydt        | «      › �}	 ddlm}  |t        |«      |«      } |||«      }|€y|j                  d¬«      }	|	rt        |	«      S dS # t        $ r=}
t        j                  d| j                  d	d
«      t        |dd
«      |
«       Y d}
~
yd}
~
ww xY w)z»Open a thread for a continuable cron job via ``adapter.create_handoff_thread``. Returns the
    thread_id, or ``None`` (no thread primitive / failed) = caller falls back to the DM mirror.Úcreate_handoff_threadNu   Hermes â€” r   ©Úsafe_schedule_threadsafeé   ©ÚtimeoutuV   Job '%s': create_handoff_thread failed on %s â€” falling back to DM-session mirror: %srz   r‡   ry   )r7   Úcallabler|   Úagent.async_utilsr’   r9   Úresultr6   rr   rŠ   r8   )rI   ÚadapterrG   ÚloopÚcreate_threadÚthread_namer’   ÚcoroÚfutureÚnew_thread_idrv   s              rB   Ú_open_continuable_cron_threadr       sÅ   € ô ˜GÐ%<¸dÓC€MÜ�MÔ" d lØØÔ 2°3Ó 7Ð8Ð9€KðÝ>ÙœS ›\¨;Ó7ˆÙ)¨$°Ó5ˆØˆ>ØØŸ™¨b˜Ó1ˆÙ%2Œs�=Ó!Ð<¸Ð<øÜò Ü�‰ð$à�G‰G�D˜#Ó¤¨°¸Ó =¸qô	Bô ûðús#   «#A0 ÁA0 Á.A0 Á0	B6Á93B1Â1B6)Ú	user_nameÚdiscord_keys_on_threadc               ó²  — ddl m} ddlm} ddlm} d}t        |dd«      }|�{	  ||j                  «       «      }|�b|r||j                  k(  rt        |«      n
t        |«      } ||||	|||||
rt        |
«      nd¬«      }|j                  |«      }t        |dd«      } ||t        |«      t        | |«      d	||d
|¬«      S # t        t        f$ r d}Y Œšw xY w)a  Create the session row (so the mirror has a target) and mirror the brief as a USER turn.
    The seeded key must equal the reply's ``build_session_key``: chat_type, user_id, thread_id and
    scope_id (Slack team id) are all part of it, so callers pass exactly what the reply carries.r   ©ÚPlatform)ÚSessionSourcer‚   NÚ_session_store)rF   rG   Ú	chat_nameÚ	chat_typerk   r¡   rW   Úscope_idÚ
session_idrN   r„   )r…   rW   rk   r†   r«   )Úgateway.configr¥   Úgateway.sessionr¦   rˆ   rƒ   r7   r:   Ú
ValueErrorÚKeyErrorÚDISCORDr9   Úget_or_create_sessionr~   )rI   r™   rX   rG   rt   rW   r©   rk   r¡   r¨   rª   r¢   r¥   r¦   rƒ   Úseeded_session_idÚsession_storeÚplatform_enumÚseed_chat_idÚdest_sourceÚ_entrys                        rB   Ú_seed_cron_sessionr¸     sÿ   € õ (Ý-Ý0Ø'+ÐÜ˜GÐ%5°tÓ<€MØÐ ð	!Ù$ ]×%8Ñ%8Ó%:Ó;ˆMð Ð$ñ
 *¨m¸x×?OÑ?OÒ.Oô �I”ä˜“\ð ñ
 (Ø&°È	Ø#Ø¨9À	Ù*2œ˜Xœ¸ô	>ˆKð #×8Ñ8¸ÓEˆFÜ '¨°¸dÓ CÐÙØ”s˜7“|Ô%9¸#¸tÓ%DØ y¸'ÈØ$ôð øô' œHÐ%ò 	!Ø ŠMð	!ús   ¥C ÃCÃCc	                óê  — |xs dj                  «       }	|	sy	 t        | ||||	t        |«      |rdn#t        j	                  |j                  «       d«      dd||d¬«      }
|
r*t        j                  d	| j	                  d
d«      |||«       yt        j                  d| j	                  d
d«      |||«       y# t        $ r4}t        j                  d| j	                  d
d«      ||||«       Y d}~yd}~ww xY w)uï  Seed the freshly-opened cron thread's session with the brief (never raises), else the
    user's in-thread reply resolves to a transcript without it. Threads are participant-shared
    (no real user_id); a DM thread must seed ``chat_type="dm"`` â€” DM-thread replies route through
    the DM arm (``â€¦:dm:<chat>:<thread>``), so a "thread"-typed seed is a row no DM reply hits.
    Non-DM threads seed the slot the platform's adapter puts on an in-thread reply
    (``_THREAD_REPLY_CHAT_TYPE``).r0   NÚdmr3   zsystem:cronÚCronT)rW   r©   rk   r¡   r¨   rª   r¢   zDJob '%s': opened continuable thread %s on %s:%s and seeded the briefrz   r‡   ud   Job '%s': thread seed did NOT land on %s:%s thread=%s â€” an in-thread reply will not see this briefz=Job '%s': seeding cron thread session failed for %s:%s:%s: %s)
r=   r¸   r9   Ú_THREAD_REPLY_CHAT_TYPEr8   r:   rr   r‰   rs   r6   )rI   r™   rX   rG   rW   r‹   r¨   rj   rª   rt   rŒ   rv   s               rB   Ú_seed_cron_thread_sessionr½   A  sü   € ð Ò˜2×$Ñ$Ó&€DÙØðFÜØ�˜-¨°$Ü˜)“nÙ#‘dÔ)@×)DÑ)DÀ]×EXÑEXÓEZÐ\dÓ)eØ!¨V¸yÐS[Ø#'ô)ˆñ Ü�K‰KØVØ—‘˜˜cÓ" I¨}¸gõGô �N‰Nð:à—‘˜˜cÓ" M°7¸IõGøô ò Fä�‰ØKØ�G‰G�D˜#Ó ¨w¸	À1÷	Fñ 	FûðFús   ™A1B5 Â)B5 Â5	C2Â>*C-Ã-C2)r¨   rª   c               ól  — |xs dj                  «       }	|	sy	 |rdnd}
t        | ||||	d|
|rt        |«      nd||¬«
      }|r)t        j	                  d| j                  dd	«      |||
«       t        |«      S # t        $ r3}t        j                  d
| j                  dd	«      |||«       Y d}~yd}~ww xY w)uÜ  Seed the FLAT (thread_id=None) session for an ``in_channel`` delivery; True on success.
    ``mirror_to_session`` only APPENDS to an existing session and the flat row is only created by
    an inbound human message, so create the row first or the brief is silently dropped. Group keys
    are user-isolated (``â€¦:group:<chat_id>:<user_id>``): the seed MUST carry the origin's real
    user_id, not ``system:cron``; DM keys omit user_id. chat_type mirrors the inbound handler.r0   Frº   rŽ   N)rW   r©   rk   r¨   rª   z@Job '%s': seeded flat in_channel session on %s:%s (chat_type=%s)rz   r‡   z9Job '%s': seeding in_channel session failed for %s:%s: %s)	r=   r¸   r9   rr   r‰   r8   rP   r6   rs   )rI   r™   rX   rG   r‹   rj   rk   r¨   rª   rt   r©   rŒ   rv   s                rB   Ú_seed_cron_channel_sessionr¿   e  sÁ   € ð Ò˜2×$Ñ$Ó&€DÙØðÙ!‘D wˆ	ÜØ�˜-¨°$ØØ¹¬¨W¬ÀdØ¨(ô	
ˆñ Ü�K‰KØRØ—‘˜˜cÓ" M°7¸IôGô �B‹xˆøÜò ä�‰ØGØ�G‰G�D˜#Ó ¨w¸ô	;ô ûðús   ™AA7 Á7	B3Â )B.Â.B3c           	     ó\  — | j                  d«      }t        |t        «      syg }dD ]l  }|j                  |«      }|€Œt        |«      j	                  dd«      j	                  dd«      j                  «       }|sŒS|j                  d|› d	|dd
 ›�«       Œn |rddj                  |«      z   S dS )z³Secret-free provenance suffix (origin platform/chat/source-IP fields) for security warnings
    about a bad stored ``context_from`` reference, where no live request object exists.rE   r0   )rF   rG   rW   Ú	source_ipÚremoteÚforwarded_forNúÚ Ú
Úorigin_Ú=éÈ   )r8   r;   r<   r9   Úreplacer=   ÚappendÚjoin)rI   rE   ÚfieldsÚkeyÚvaluert   s         rB   Ú_cron_job_origin_log_suffixrÐ   †  s³   € ð �W‰W�XÓ€FÜ�fœdÔ#ØØ€FØ[ò :ˆØ—
‘
˜3“ˆØˆ=ØÜ�5‹z×!Ñ! $¨Ó,×4Ñ4°T¸3Ó?×EÑEÓGˆÚØ�M‰M˜G C 5¨¨$¨t°¨*¨Ð8Õ9ð:ñ &,ˆ3�—‘˜&Ó!Ñ!Ð3°Ð3rK   c                ó
  — t        j                  t        «      5  ddlm}  |«        ddlm} |j                  | j                  «       «      }|r!|j                  r|j                  cddd«       S ddd«       y# 1 sw Y   yxY w)zXCron home-channel env var registered by a plugin ``PlatformEntry.cron_deliver_env_var``.r   ©Údiscover_plugins©Úplatform_registryNr0   )
r4   r5   r6   Úhermes_cli.pluginsrÓ   Úgateway.platform_registryrÕ   r8   r:   Úcron_deliver_env_var)rX   rÓ   rÕ   Úentrys       rB   Ú_plugin_cron_env_varrÚ   —  sm   € ä	×	Ñ	œYÓ	'ñ .Ý7ÙÔÝ?Ø!×%Ñ% m×&9Ñ&9Ó&;Ó<ˆÙ�U×/Ò/Ø×-Ñ-÷.÷ .ñ .ð ÷.ð ús   šAA9Á9Bc                ó^   — | j                  «       }|t        v xs t        t        |«      «      S )zRValid cron delivery platform: built-in, or plugin with a ``cron_deliver_env_var``.)r:   Ú_KNOWN_DELIVERY_PLATFORMSrP   rÚ   ©rX   ry   s     rB   Ú_is_known_delivery_platformrÞ   £  s,   € à×ÑÓ €DØÔ,Ð,ÒP´Ô5IÈ$Ó5OÓ0PÐPrK   c                óf   — | j                  «       }t        j                  |«      xs t        |«      S )zWEnv var name for a platform's cron home channel (built-in table, then plugin registry).)r:   Ú_HOME_TARGET_ENV_VARSr8   rÚ   rÝ   s     rB   Ú_resolve_home_env_varrá   ©  s,   € à×ÑÓ €DÜ ×$Ñ$ TÓ*ÒHÔ.BÀ4Ó.HÐHrK   c                ó¶   — 	 ddl m}m}  |«       j                   || j	                  «       «      «      S # t
        $ r t        j                  d| d¬«       Y yw xY w)u  Persisted ``HomeChannel`` from gateway config â€” the canonical store ``/sethome`` writes.
    The ``<PLATFORM>_HOME_CHANNEL`` env var is only a best-effort mirror; relay-fronted platforms
    may exist solely in config.yaml, so reading only the env mirror would drop their delivery.r   )Úload_gateway_configr¥   z1config home_channel lookup failed for platform %rT©Úexc_infoN)r¬   rã   r¥   Úget_home_channelr:   r6   rr   rŠ   )rX   rã   r¥   s      rB   Ú_get_config_home_channelrç   ¯  sX   € ðß@Ù"Ó$×5Ñ5±h¸}×?RÑ?RÓ?TÓ6UÓVÐVøÜò Ü�‰Ø?ÀÐY]ð 	ô 	_áðús   ‚14 ´!AÁA©r=   c               ó¦   ‡‡— 	 ddl mŠ dˆˆfd„} || |z   «      }t        j	                  | «      }|s|r |||z   «      }|S # t        $ r dŠY ŒEw xY w)ao  Value of ``<env_var><suffix>``, falling back to the legacy name (same suffix) when unset.
    Reads via ``get_secret``, not ``os.getenv``: in a multiplex gateway the tick runs with the
    job-owning profile's secret scope (run_one_job sets it), so this resolves the OWNING profile's
    value, not the host environ. ``os.getenv`` only if the scope module is missing.r   )Ú
get_secretNc                óv   •— ‰� ‰| d«      xs dnt        j                  | d«      }‰r|j                  «       S |S )Nr0   )ÚosÚgetenvr=   )ry   rÏ   rê   r=   s     €€rB   Úreadz_home_env_lookup.<locals>.readÆ  s;   ø€ Ø0:Ð0F‘˜D "Ó%Ò+©ÌBÏIÉIÐVZÐ\^ÓL_ˆÙ %ˆu�{‰{‹}Ð0¨5Ð0rK   )ry   r9   Úreturnr9   )Úagent.secret_scoperê   r6   Ú_LEGACY_HOME_TARGET_ENV_VARSr8   )Úenv_varÚsuffixr=   rî   rÏ   Úlegacyrê   s     `   @rB   Ú_home_env_lookuprõ   ¼  s_   ù€ ð
Ý1ö1ñ �˜6Ñ!Ó"€EÜ)×-Ñ-¨gÓ6€FÙ‘VÙ�V˜f‘_Ó%ˆØ€Løô ò ØŠ
ðús   „A ÁAÁAc                ó6   — t        | «      }|rt        |«      S dS )uU  Home chat id from the env mirror only (no config).

    Reads through ``get_secret`` (not raw ``os.getenv``) so a profile-scoped secret scope wins in a
    multiplex gateway. ``DISCORD_HOME_CHANNEL`` lives in each profile's ``.env``; in a multiplex process the
    winning cron tick runs with the job-owning profile's scope installed (run_one_job sets it), so reading
    via ``get_secret`` resolves the OWNING profile's chat id rather than the host process's ``os.environ``
    (#83182, chat-id leg â€” the token leg was fixed earlier; chat id / thread id resolve through the same
    leak).
    r0   )rá   rõ   )rX   rò   s     rB   Ú_env_home_target_chat_idr÷   Ñ  s!   € ô $ MÓ2€GÙ(/Ô˜GÓ$Ð7°RÐ7rK   c                ó€   — t        | «      }|r|S t        | «      }|�!|j                  rt        |j                  «      S dS )ux   Home target chat id: env var (first, so operator overrides win) â†’ legacy env var â†’
    config.yaml ``home_channel``.r0   )r÷   rç   rG   r9   )rX   rÏ   r_   s      rB   Ú_get_home_target_chat_idrù   ß  s?   € ô % ]Ó3€EÙØˆÜ# MÓ2€DØ $Ð 0°T·\²\Œ3ˆt�|‰|ÓÐIÀrÐIrK   c                ó   — | j                  «       dk(  rt        dd¬«      }|r|S t        | «      }|rt        |dd¬«      nd}|r|S t        | «      s.t	        | «      }|�!|j
                  rt        |j
                  «      S y)ud  Optional thread/topic id for a platform home target. Telegram: ``TELEGRAM_CRON_THREAD_ID``
    overrides ``TELEGRAM_HOME_CHANNEL_THREAD_ID`` â€” in topic mode a root-DM delivery lands in the
    system-only lobby where the user cannot reply.

    When topic mode is enabled, deliveries that land in the root DM (thread_id unset) end up in the
    system-only lobby where the user cannot reply â€” the gateway returns the lobby reminder and drops
    ``reply_to_message_id`` (#24409). Pointing cron at a dedicated topic via this env var lets replies work
    as expected without changing the lobby invariant.
    r   ÚTELEGRAM_CRON_THREAD_IDTrè   Ú
_THREAD_IDr0   N)r:   rõ   rá   r÷   rç   rW   r9   )rX   Úcron_threadrò   rÏ   r_   s        rB   Ú_get_home_target_thread_idrþ   é  sƒ   € ð ×ÑÓ 
Ò*Ü&Ð'@ÈÔMˆÙØÐÜ# MÓ2€GÙCJÔ˜W l¸$Õ?ÐPR€EÙØˆô $ MÔ2Ü'¨Ó6ˆØÐ §¢Ü�t—~‘~Ó&Ð&ØrK   c               #  ó6  K  — t         E d{  –—†  t        j                  t        «      5  ddlm}   | «        ddlm} |j                  «       D ]0  }|j                  sŒ|j                  t         vsŒ#|j                  –— Œ2 	 ddd«       y7 Œ~# 1 sw Y   yxY w­w)zDIterate built-in + plugin platform names that expose a home channel.Nr   rÒ   rÔ   )rà   r4   r5   r6   rÖ   rÓ   r×   rÕ   Úplugin_entriesrØ   ry   )rÓ   rÕ   rÙ   s      rB   Ú_iter_home_target_platformsr    s   è ø€ ä$×$Ð$Ü	×	Ñ	œYÓ	'ñ !Ý7ÙÔÝ?Ø&×5Ñ5Ó7ò 	!ˆEØ×)Ó)¨e¯j©jÔ@UÒ.UØ—j‘jÓ ñ	!÷	!ð !ð %ø÷!ð !üs2   ‚
BŒB�Bª3BÁBÁ1BÂ
BÂBÂBc                óš   — d| vr
t        «       S 	 ddlm}  |«       S # t        $ r$ t        j                  dd¬«       t        «       cY S w xY w)a  Logical platforms deliverable through a connected relay. ``get_connected_platforms()`` only
    sees native platforms; fronted ones come from the same ``GATEWAY_RELAY_PLATFORMS`` stamp
    fire-time routing uses (validation symmetric with routing). No relay -> empty set.Úrelayr   ©Úrelay_fronted_platformsz$relay fronted-platform lookup failedTrä   )ÚsetÚgateway.relayr  r6   rr   rŠ   )Ú	connectedr  s     rB   Ú!_relay_fronted_delivery_platformsr	    sK   € ð �iÑÜ‹uˆðÝ9Ù&Ó(Ð(øÜò Ü�‰Ð;ÀdˆÔKÜ‹uŠðús   � �*A
Á	A
c            
     ó–  — g } 	 ddl m}  |«       j                  «       D �ch c]  }|j                  ’Œ }}|t	        |«      z  }t        «       D ]e  }||vst        |«      sŒ| j                  ||j                  dd«      j                  «       t        t        |«      «      t!        |«      xs dd	œ«       Œg 	 dd
lm}  |«       D ]%  }| j                  t&        › d|› �d|› d�ddd	œ«       Œ' 	 | S c c}w # t
        $ r$ t        j                  dd¬«       t        «       }Y ŒÜw xY w# t
        $ r t        j                  dd¬«       Y | S w xY w)aK  Platforms a cron job can auto-deliver to (single source of truth for UIs): valid delivery
    platform AND gateway-configured; ``home_target_set`` flags whether the home channel exists.
    ``{"id", "name", "home_target_set", "home_env_var"}`` dicts in canonical order; callers
    prepend the implicit ``local`` option themselves.r   ©rã   z1cron_delivery_targets: gateway config unavailableTrä   Ú_rÅ   N)rz   ry   Úhome_target_setÚhome_env_var)Úlist_profile_namesú:z
Bot Chat (ú)z2cron_delivery_targets: profile listing unavailable)r¬   rã   Úget_connected_platformsrÏ   r	  r6   rr   rŠ   r  r  rÞ   rË   rÊ   ÚtitlerP   rù   rá   Úhermes_cli.profilesr  ÚBOT_CHAT_PLATFORM)Útargetsrã   Úpr  ry   r  Úprofile_names          rB   Úcron_delivery_targetsr    s`  € ð
 €GðÝ6Ù&9Ó&;×&SÑ&SÓ&UÖV �Q—W“WÐVˆ	ÐVØÔ6°yÓAÑAˆ	ô
 ,Ó-ò BˆØ�yÑ Ô(CÀDÔ(IØØ�‰ØØ—L‘L  cÓ*×0Ñ0Ó2Ü#Ô$<¸TÓ$BÓCÜ1°$Ó7Ò?¸4ñ	Aõ 	BðBð	ZÝ:Ù.Ó0ò 	'ˆLØ�N‰NÜ*Ð+¨1¨\¨NÐ;Ø$ \ N°!Ð4Ø#'Ø $ñ	&õ 'ñ	'ð €Nùò5 Wøäò Ü�‰ÐHÐSWˆÔXÜ“EŠ	ðûô, ò ZÜ�‰ÐIÐTXˆÕYØ€NðZús3   „C4 ¡C/´C4 Â75D$ Ã/C4 Ã4*D!Ä D!Ä$ EÅEc                ó   — t        | j                  d«      xs d«      j                  «       dk7  s| j                  d«      syt        d«      }t	        |«      xr& t        | j                  d«      «      t        |«      k(  S )a{  True when a Slack origin's thread is a stale creation-turn artifact. Thread-per-message
    Slack stamps each top-level message id as the session thread (a KEY, not a location); old jobs
    carry it as ``origin.thread_id``. Heuristic: if the origin chat IS the Slack home chat, the
    pinned thread is that artifact and delivery goes top-level (or to the home target's thread).rF   r0   r   rW   FrG   )r9   r8   r:   rù   rP   )rE   Ú	home_chats     rB   Ú_origin_thread_is_staler  C  sf   € ô
 ˆ6�:‰:�jÓ!Ò' RÓ(×.Ñ.Ó0°GÒ;À6Ç:Á:ÈkÔCZØÜ(¨Ó1€IÜ�	‹?ÒKœs 6§:¡:¨iÓ#8Ó9¼SÀ»^ÑKÐKrK   c                óX   — t        | «      rt        d«      xs dS | j                  d«      S )zAThe thread a deliver=origin job should use, stale stamps dropped.r   NrW   )r  rþ   r8   )rE   s    rB   Ú_origin_delivery_threadr  N  s)   € ä˜vÔ&Ü)¨'Ó2Ò:°dÐ:Ø�:‰:�kÓ"Ð"rK   c                ó2   — | |t        | «      dœ}|r||d<   |S )zTTarget dict for a platform's configured home channel (+ optional mirror provenance).©rF   rG   rW   rc   )rþ   )rX   rG   rf   rd   s       rB   Ú_home_targetr!  U  s/   € ð "ØÜ/°Ó>ñ@€Fñ Ø#0ˆÐÑ Ø€MrK   ©Úfrom_broadcastc               óP  — t        | «      }|dk(  ryt        |«      }|�t        | |«      S |dk(  r„|r|d   t        |d   «      t	        |«      ddœS t        «       D ]U  }t        |«      }|sŒt        j                  d| j                  d| j                  d	d
«      «      |«       t        ||d«      c S  yd|v rï|j                  dd«      \  }}|j                  «       }ddlm}	m}
  |	«         |
||d¬«      \  }}}|rt        j!                  d||«       y|€‰|dk(  r„|r‚t        |j                  d«      xs d«      j                  «       |k(  rSt        |j                  d«      «      t        |«      k(  r-|j                  d«      rt#        |«      s|j                  d«      }|||ddœS |}|rdnd}|rO|j                  d«      |k(  r;t        |«      }|rt        |||«      S |t        |d   «      |j                  d«      dœS t%        |«      syt        |«      }|rt        |||«      S dS )aŽ  Resolve one concrete auto-delivery target for a cron job.

    ``from_broadcast`` marks a bare-platform token that was produced by expanding a broadcast
    token (``all``) rather than written by the user; broadcast expansions carry no mirror
    provenance (fan-out is never continuable), while a user-written bare platform token is a
    deliberate home-channel address and gets the ``home`` tag.ÚlocalNrE   rF   rG   )rF   rG   rW   rc   zJJob '%s' has deliver=origin but no origin; falling back to %s home channelry   rz   r‡   r^   r  r]   r   )Úprepare_send_message_platformsÚresolve_send_targetT)Úpass_unresolved_referencesz%Invalid cron delivery target '%s': %sr   r0   rW   r`   r_   r   )rJ   Úparse_bot_chat_deliver_tokenÚ_resolve_bot_chat_targetr9   r  r  rù   rr   r‰   r8   r!  Úsplitr:   Útools.send_message_toolr&  r'  rs   r  rÞ   )rI   Údeliver_valuer#  rE   Úbot_chat_profilerX   rG   ÚrestÚplatform_keyr&  r'  rW   Úresolution_errorÚhome_provenances                 rB   Ú_resolve_single_delivery_targetr3  `  sY  € ô ˜SÓ!€FØ˜ÒØä3°MÓBÐØÐ#Ü'¨Ð-=Ó>Ð>à˜Ò Ùà" :Ñ.Ü˜v iÑ0Ó1Ü4°VÓ<Ø"*ñ	ð ô 9Ó:ò 	OˆMÜ.¨}Ó=ˆGÚÜ—‘Ø`Ø—G‘G˜F C§G¡G¨D°#Ó$6Ó7¸ôHô $ M°7Ð<MÓNÒNð	Oð à
ˆmÑØ+×1Ñ1°#°qÓ9Ñˆ�tØ$×*Ñ*Ó,ˆß_Ù&Ô(ñ 0CØ˜$¸4ô0AÑ,ˆ�Ð,áÜ�N‰NÐBÀMÐScÔdØàÐØ Ò'ÙÜ�F—J‘J˜zÓ*Ò0¨bÓ1×7Ñ7Ó9¸\ÒIÜ�F—J‘J˜yÓ)Ó*¬c°'«lÒ:Ø—
‘
˜;Ô'Ü+¨FÔ3àŸ
™
 ;Ó/ˆIà%ØØ"Ø(ñ	
ð 	
ð "€MÙ,‘d°&€OÙ�&—*‘*˜ZÓ(¨MÒ9Ü*¨=Ó9ˆÙÜ ¨w¸ÓHÐHð &Ü˜6 )Ñ,Ó-ØŸ™ KÓ0ñ
ð 	
ô
 ' }Ô5ØÜ& }Ó5€GÙDKŒ<˜ w°Ó@ÐUÐQUÐUrK   c                 ó²   — 	 t        j                  «       } t        | j                  di «      j                  dd«      «      }|dkD  r|S dS # t        $ r Y yw xY w)u‘   Timeout for one bot-chat delivery turn (a full agent turn â€” minutes, not seconds).
    ``cron.bot_chat_delivery_timeout_seconds``; default 600.rN   Ú!bot_chat_delivery_timeout_secondsiX  r   ©rQ   rR   Úintr8   r6   ©rS   rÏ   s     rB   Ú_get_bot_chat_delivery_timeoutr9  ³  s\   € ðÜ× Ñ Ó"ˆÜ�C—G‘G˜F BÓ'×+Ñ+Ð,OÐQTÓUÓVˆØ š	ˆuÐ* sÐ*øÜò Ùðúó   ‚AA
 ÁA
 Á
	AÁAc                 ó²   — 	 t        j                  «       } t        | j                  di «      j                  dd«      «      }|dkD  r|S dS # t        $ r Y yw xY w)u[  Wall-clock bound for one standalone-lane send (#115469).

    ``_send_to_platform``'s gateway-loop dispatch deliberately awaits its future with no
    timeout ("the adapter and outer _run_async bound the wait") â€” but on this lane the
    outer runner is a bare ``asyncio.run``, not ``model_tools._run_async``, so without a
    bound here a reconnecting transport pins the run (and the restart drain behind it)
    indefinitely. Mirrors the sibling lanes: live dispatch ``future.result(timeout=60)``,
    thread fallback ``result(timeout=30)``. ``cron.standalone_send_timeout_seconds``;
    default 60.rN   Ústandalone_send_timeout_secondsé<   r   r6  r8  s     rB   Ú_get_standalone_send_timeoutr>  ¾  s[   € ðÜ× Ñ Ó"ˆÜ�C—G‘G˜F BÓ'×+Ñ+Ð,MÈrÓRÓSˆØ š	ˆuÐ) rÐ)øÜò Ùðúr:  iô  rÉ   )zResumed sessionzsession_id:c           	     óN   — ddl m}  || ||||j                  d«      xs d¬«      S )am  Run one ``hermes chat -Q`` delivery child; the cap bounds the TURN, not the process (#113608).

    The booking policy lives with the report contract (``quiet_single_query.run_reported_turn``):
    this lane needs only the outcome, so a child that reported its turn gets the exit grace and is
    then left to its linger; only a turn that never ends is killed.
    r   )Úrun_reported_turnÚHERMES_HOMEN)ÚenvÚreport_pathr•   Úcwd)Úhermes_cli.quiet_single_queryr@  r8   )ÚargvrB  rC  r•   r@  s        rB   Ú_run_bot_chat_turnrG  Ö  s2   € õ @ñ ˜T s¸ÈWØ!$§¡¨Ó!7Ò!?¸4ôAð ArK   c                ó¬  — ddl m} t        | dd«      xs dj                  «       }t        | dd«      xs dj                  «       }dt        | dd	«      › �g}|r|j	                  d
|t
         d › �«       |rFdj                  d„ |j                  «       D «       «      }|j	                  |rd|t         d › �nd«        |dj                  |«      dd¬«      S )uu  Exit code plus labeled, redacted stderr/stdout tails for a failed delivery turn.

    ``-Q`` reports the resume banner and ``session_id:`` while the response
    rides stdout, so ``stderr or stdout`` discarded half the signal â€” and when
    stderr is empty and stdout holds only the banner, the recorded error
    carried zero diagnostics (#104056). The banner lines are dropped from the
    stdout tail so what remains is the reason; the exit code is always named.
    The text lands in ``last_delivery_error`` on disk, so it is scrubbed like
    ``cron.incidents`` / ``cron.delivery_queue`` scrub their persisted errors.
    r   rn   ÚstderrNr0   Ústdoutz
exit code Ú
returncoder‡   zstderr: rÆ   c              3  ó¤   K  — | ]H  }|j                  «       r6|j                  «       j                  d «      j                  t        «      s|–— ŒJ y­w)u   â†» N)r=   ÚlstripÚ
startswithÚ_BOT_CHAT_BANNER_PREFIXES)Ú.0Úlines     rB   ú	<genexpr>z*_format_failure_streams.<locals>.<genexpr>û  sB   è ø€ ò gØØ�z‰zŒ| D§J¡J£L×$7Ñ$7¸Ó$?×$JÑ$JÔKdÔ$eô ñgùs   ‚AAzstdout: z!stdout was only the resume bannerz | T)rp   Úredact_url_credentials)	rq   ro   r7   r=   rË   Ú_BOT_CHAT_STDERR_TAILrÌ   Ú
splitlinesÚ_BOT_CHAT_STDOUT_TAIL)r˜   ro   ÚerrÚoutÚpartsÚkepts         rB   Ú_format_failure_streamsr[  è  sè   € õ 3ä�6˜8 TÓ*Ò0¨b×
7Ñ
7Ó
9€CÜ�6˜8 TÓ*Ò0¨b×
7Ñ
7Ó
9€CØœ' &¨,¸Ó<Ð=Ð>Ð?€EÙ
Ø�‰�x Ô%:Ð$:Ð$;Ð <Ð=Ð>Ô?Ù
Ø�y‰yñ gØ Ÿ^™^Ó-ôgó gˆð 	�‰Ù:>ˆh�tÔ2Ð2Ð3Ð4Ð5Ñ6Ø4ô	6ñ ! §¡¨EÓ!2¸$ÐW[Ô\Ð\rK   )ÚdeferredÚfor_failurec          
     óÒ  ‡;— ddl }ddl}ddl}ddl}ddlm}	 ddlm}
 ddlm	}m
}m} | j                  dd«      Š;|xs d}t        |d	«      }t        | j                  d
‰;«      d«      }d|› d|› �}	  |	«       j                  «       }ddlm} |� ||d   «      n|r |
|«      n|j                  «       }|xs t#        |xs i j                  d«      «      }ddlm} ddlm} |xr  |t,         ||dz  «      «       }|�|dz  j/                  «       sd|› d�S | j                  d«      }|s*| j1                  d|j3                  «       j4                  «      }|j7                  |j9                  t;        |«      ‰;t;        |«      t;        |«      gdd¬«      j=                  d«      «      j?                  «       }|�|d   } |||«      }|€ƒ|s�ddl m!}m"} ddlm#}  ||«      }|€|s ||«      €  ||«      r ||tI        | «      |||||¬«      }|�=|d    }d!|› �}||d"œ| j1                  d#i «      |<   |d$k(  rd%| d&<   |d'v rdS |› d(|› d)|› d*�S |€ ||«      } | � ||| |fd+|i|rd,d-ini ¤Ž}|�ª|d.   |k7  s|j                  d,d/«      |rd-nd/k7  rtK        d0«      ‚|d    }d!|› �}| j1                  d#i «      }!||d"œ|!|<   tL        jO                  d1‰;|||«       |d2k(  ry|d3v rd4n'|j                  d5«      xs |j                  d6«      xs d7}"|› d(|› d)|› d8|"› �S 	 	 ddl)m*}$ |$jW                  d;«      du}%|%rtX        jZ                  d<d=g}&nt]        j^                  d>«      }'|'sy?|'g}&dnˆ;fd@„}(ddAl0m1}) ddBl2m3}* |ji                  «       s |(d|› d�«      S 	  |* |)tj        jl                  «      |d%¬C«      }+|jr                  jt                  dGk7  r|&dHdIgz  }&d},	 |jw                  dJddKdLd¬M«      5 }-|-jy                  |«       |-jt                  },ddd«       |&dNdOdPdQdRdSdTdU|,g	z  }&ddVl=m>}. |,› dW�}/|/|+|.<   t        «       }0t�        |&|+|/|0«      }1|1j‚                  dk7  rst…        |1«      }2tL        j‡                  dX‰;|||2«       dY|› dZ|2› �	 |,rD|,|,› dW�fD ]9  }3t‰        jŠ                  tŒ        «      5  tk        jŽ                  |3«       ddd«       Œ; S S tL        jO                  d[‰;|«       	 |,rD|,|,› dW�fD ]9  }3t‰        jŠ                  tŒ        «      5  tk        jŽ                  |3«       ddd«       Œ; yy# tP        $ r}#d9|› d:|#› �cY d}#~#S d}#~#ww xY w# tP        $ r d}%Y �Œ!w xY w# tP        $ r/}# |(d9|› dDto        |#«      jp                  › dE|#› dF�«      cY d}#~#S d}#~#ww xY w# 1 sw Y   �ŒŒxY w# 1 sw Y   �ŒxY w# 1 sw Y   ŒÌxY w# t�        j’                  $ �r$ d}4|xs i j                  d\«      sœd]0› d^‰;› d_|j•                  «       dd` › �}5	 ddal m!}6 |j7                  |› db�j=                  d«      «      j?                  «       }7 |6|7tI        | «      |5|||d%¬c«       d%}4n-# tP        $ r!}8tL        j‡                  dd‰;|8«       Y d}8~8nd}8~8ww xY w|4rde‰;› df�ndg}9 |(d9|› dh0› di|9› dj�«      cY |,rP|,|,› dW�fD ]E  }3t‰        jŠ                  tŒ        «      5  tk        jŽ                  |3«       ddd«       Œ;# 1 sw Y   ŒDxY w S S tP        $ rœ}:tL        j‡                  dk‰;|t;        |:«      xs to        |:«      jp                  d%¬l«       dY|› dm�cY d}:~:|,rP|,|,› dW�fD ]E  }3t‰        jŠ                  tŒ        «      5  tk        jŽ                  |3«       ddd«       Œ;# 1 sw Y   ŒDxY w S S d}:~:ww xY w# |,rP|,|,› dW�fD ]E  }3t‰        jŠ                  tŒ        «      5  tk        jŽ                  |3«       ddd«       Œ;# 1 sw Y   ŒDxY w w w xY w)oaâ  Hand output to the live Bot Chat owner, or use the legacy unowned CLI lane.

    None means completed; a queued/claimed receipt returns an explicit unverified status
    string so existing Optional[str] callers cannot misreport admission as delivery.
    ``profile`` is ``""`` for the job's own profile. A ``for_failure`` notice whose target
    profile hides warning notifications is recorded as ``suppressed`` (a durable
    disposition, never a send) and flagged on the job.
    r   N)Úget_hermes_home)Úget_profile_dir)Údeliver_to_live_ownerÚfind_canonical_live_ownerÚread_delivery_resultrz   r‡   ú(own)zbot-chat payloadry   r{   z
[Cronjob "uv   " output â€” scheduled job, not the user. Review it, act on anything that needs action, and summarize for the chat.]

)ÚPathr_   r]  ©Úwarning_notifications_enabled)Úload_user_config_effectivezconfig.yamlzstate.dbz+bot-chat delivery target no longer exists: z; do not resendÚexecution_idÚ_bot_chat_run_idF)ú,r  )Úensure_asciiÚ
separatorszutf-8)ÚdeferÚread_pending)Úfind_canonical_owner)r]  Ú
suppressedÚstatusú	bot-chat:)rr  Údelivery_idÚ_bot_chat_delivery_receiptsrq  TÚ$_notification_all_targets_suppressed)Úsettledrq  rÅ   z
 (receipt z'): completion unverified; do not resendrt  Únotification_categoryÚ
diagnosticÚmessager˜   z2delivery id already belongs to a different payloadz*Job '%s': Bot Chat %s receipt=%s status=%srw  ©ÚqueuedÚclaimedz$completion unverified; do not resendÚerrorÚreasonznot completedz): zbot-chat delivery to profile 'z' unverified: Ú
hermes_cliz-mzhermes_cli.mainÚhermesz·Hermes could not deliver this result to Bot Chat: the `hermes` command was not found. The result is saved; run `hermes cron runs` to see it, or `hermes doctor` if this keeps happeningc                ó8   •— t        j                  d‰| fi |¤Ž | S )NúJob '%s': %s©rr   rs   )ÚmsgÚ
log_kwargsÚjob_ids     €rB   Ú_failz#_deliver_to_bot_chat.<locals>._fail|  s   ø€ Ü�‰�~ v¨sÑA°jÒAØˆ
rK   )Údelegated_child_subprocess_env)Úserved_profile_child_env)Útarget_homeÚinherit_credentialsz4' could not build the target profile's environment (ú: z); do not resendÚprofilesz-pÚdefaultÚwz.txtzhermes-cron-botchat-)Úencodingró   ÚprefixÚdeleteÚchatz--inÚ~z-czBot Chatz--create-if-missingz-Qz--query-file)ÚTURN_REPORT_FILE_ENVz
.turn.jsonz<Job '%s': bot-chat delivery to profile '%s' failed at %s: %sz;Hermes could not deliver this result to Bot Chat (profile 'zp'). The result is saved; run `hermes cron runs` to see it, or `hermes doctor` if this keeps happening. Details: z/Job '%s': delivered to Bot Chat of profile '%s'Údegradedz>DELIVERY DEGRADED: this alert's bot-chat turn timed out after zms, so the full output could NOT be posted here. Read the complete saved output with `hermes cron runs` (job 'z'). Excerpt: i  )rn  z	:degraded)r]  r—  z:Job '%s': degraded-delivery marker could not be queued: %su”   a short degraded-delivery notice was queued to Bot Chat â€” posted once the session frees; full output stays saved, run `hermes cron runs` for job 'ú'zathe result is saved; run `hermes cron runs` to see it, or `hermes doctor` if this keeps happeningz' timed out after zs (z>; raise cron.bot_chat_delivery_timeout_seconds if this recurs)z6Job '%s': bot-chat delivery to profile '%s' failed: %srä   ze'). The result is saved; run `hermes cron runs` to see it, or `hermes doctor` if this keeps happening)r…  r9   rï   r9   )KÚhashlibÚjsonÚtempfileÚuuidÚhermes_constantsr_  r  r`  Útools.bot_live_deliveryra  rb  rc  r8   rw   ÚresolveÚpathlibre  rP   Úgateway.warning_notificationsrg  Úhermes_cli.config_effectiverh  ÚBOT_CHAT_POLICY_PLATFORMÚis_fileÚ
setdefaultÚuuid4ÚhexÚsha256Údumpsr9   ÚencodeÚ	hexdigestÚcron.bot_chat_deliveryrn  ro  rp  r<   r®   rr   r‰   r6   Úimportlib.utilÚutilÚ	find_specÚsysÚ
executableÚshutilÚwhichÚagent.delegation_contextr‰  Útools.environments.localrŠ  Úis_dirrì   ÚenvironÚtypeÚ__name__Úparentry   ÚNamedTemporaryFileÚwriterE  r–  r9  rG  rK  r[  rs   r4   r5   ÚOSErrorÚunlinkÚ
subprocessÚTimeoutExpiredr=   )<rI   ÚcontentÚprofiler\  r]  r™  rš  r›  rœ  r_  r`  ra  rb  rc  Úprofile_labelÚjob_namerz  Úsource_homere  r_   rg  rh  Úsuppress_notificationÚrun_idrÎ   Úreceiptrn  ro  rp  Úpendingrr  rd   ÚownerÚreceiptsÚdetailÚexcÚ_iluÚfoundrF  Ú
hermes_binrˆ  r‰  rŠ  rB  Ú
query_fileÚfhr–  Úreport_fileÚ	timeout_sr˜   ÚtailÚpathÚmarker_queuedÚmarkerÚ_defer_markerÚ
marker_keyÚ	defer_excÚhintrv   r‡  s<                                                              @rB   Ú_deliver_to_bot_chatrÝ    sƒ	  ø€ ó ÛÛÛÝ0Ý3÷ñ ð �W‰W�T˜3Ó€FØÒ&˜w€Mô
 # 7Ð,>Ó?€GÜ# C§G¡G¨F°FÓ$;¸ZÓH€Hà
�X�Jð 'à'. ið	1ð ð
DSÙ%Ó'×/Ñ/Ó1ˆÝ Ø*2Ð*>‘�X˜fÑ%Ô&Ù,3‘ Ô(¸ÇgÁgÃið 	à!ÒN¤T¨8ª>°r×*>Ñ*>¸}Ó*MÓ%NˆÝOÝJØ +ò !XÑ4QÜ$Ñ&@ÀÈÑAUÓ&Vó5Xð 1XÐàÐ¨°
Ñ):×(CÑ(CÔ(EØ@ÀÀÀoÐVÐVð —‘˜Ó(ˆÙØ—^‘^Ð$6¸¿
¹
»×8HÑ8HÓIˆFØ�n‰n˜TŸZ™ZÜ�Ó˜v¤s¨6£{´C¸³IÐ>Ø¨:ð (ó 
÷ ‰&�‹/ó÷ %™9›;ð 	ð ÐØ˜4‘.ˆCñ ' t¨SÓ1ˆØˆ?¡8ßBÝDá" 3Ó'ˆGð Ð#Ñ'<Ù1°$Ó7Ð?ÑDXÐY]ÔD^Ù ¤T¨#£Y°¸À$Ø,7ÐDYô[�àÐ"Ø  Ñ*�Ø$ ] OÐ4�à$°SñM:�—‘Ð<¸bÓAÀ&ÑIà˜\Ò)ØBF�CÐ>Ñ?Ø%Ð)BÑB�tð  SÈ6È(ÐRSÐTZÐS[Ð[eÐfiÐejð  kRð  ISð  SØˆ?Ù-¨dÓ3ˆEØÐ Ù/°°e¸Wñ XÐRUð XÙBMÐ/°Ñ>ÐSUñX�àÐØ˜	Ñ" gÒ-Ø—{‘{Ð#:¸HÓEÑZeÉ,ÐksÒtÜ Ð!UÓVÐVØ˜XÑ&ˆFØ   Ð0ˆFØ—~‘~Ð&CÀRÓHˆHØ*0ÀÑEˆH�VÑÜ�K‰KÐDØ ¨s°Fô<à˜Ò"ØØ@FÐJ_Ñ@_Ñ<Ø"Ÿ;™; wÓ/Ò[°7·;±;¸xÓ3HÒ[ÈOð à�X˜Q˜v˜h j°°°S¸¸ÐAÐAð ð,Ý%Ø—‘˜|Ó,°DÐ8ˆñ Ü—‘ Ð&7Ð8‰ä—\‘\ (Ó+ˆ
Ùðxàˆ|ˆõõ HÝAØ�;‰;Œ=ÙÐBÀ4À&ÈÐXÓYÐYð\Ù&Ù*¬2¯:©:Ó6ÀDÐ^bôdˆð
 ‡{�{×Ñ˜:Ò%Ø��yÐ!Ñ!ˆà€JðJ$Ø×(Ñ(Ø˜'¨&Ð9OÐX]ð )ó 
ð 	!àØ�H‰H�WÔØŸ™ˆJ÷		!ð 	Ø�F˜C  zÐ3HØ�. *ð
ñ 	
ˆõ 	GØ#˜ JÐ/ˆØ$/ˆÐ Ñ!Ü2Ó4ˆ	Ü# D¨#¨{¸IÓFˆØ×Ñ Ò!Ü*¨6Ó2ˆDÜ�N‰NØNØ˜ t¨Tô3ð NÈmÈ_ð ]à"˜Vð%ð&ñd Ø#¨
 |°:Ð%>Ð?ò $�Ü×(Ñ(¬Ó1ñ $Ü—I‘I˜d”O÷$ð $ñ$ð ô] 	�‰ÐEÀvÈ}Ô]ØñZ Ø#¨
 |°:Ð%>Ð?ò $�Ü×(Ñ(¬Ó1ñ $Ü—I‘I˜d”O÷$ð $ñ$ð øôg ò Sà/°¨¸nÈSÈEÐRÕRûðSûô ò Ø‹ðûô6 ò \ÙÐ5°m°_ð E/Ü/3°C«y×/AÑ/AÐ.BÀ"ÀSÀEÐIYð[ó \õ 	\ûð\ú÷	!ñ 	!ú÷P$ñ $ú÷ $ð $ûô] ×$Ñ$ó #Fð
 ˆØ’˜B×#Ñ# JÔ/àPØ�+ð GØGMÀhð OØ#ŸM™M›O¨D¨SÐ1Ð2ð4ð ð'ÝIð %Ÿ^™^¨s¨e°9Ð,=×,DÑ,DÀWÓ,MÓN×XÑXÓZ�
Ù˜j¬$¨s«)°V¸WÀdØ*5ÀõFà $‘øÜò 'Ü—‘ØPØ˜I÷'ñ 'ûð'úñ ðWØW]ÐV^Ð^_ñað&ð	 	ñ Ø,¨]¨Oð <Ø�K˜s 4 &ð )EðEóFñ 	Fñ Ø#¨
 |°:Ð%>Ð?ò $�Ü×(Ñ(¬Ó1ñ $Ü—I‘I˜d”O÷$÷ $ñ $úñ$ð ô ò qÜ�‰ØDÀfÈmÜ�‹FÒ&”d˜1“g×&Ñ&°ð 	ô 	7ð JÈ-Èð Ypð pô	qñ Ø#¨
 |°:Ð%>Ð?ò $�Ü×(Ñ(¬Ó1ñ $Ü—I‘I˜d”O÷$÷ $ñ $úñ$ð ûðqûñ Ø#¨
 |°:Ð%>Ð?ò $�Ü×(Ñ(¬Ó1ñ $Ü—I‘I˜d”O÷$÷ $ñ $úñ$ð ús8  Á1B%T# ÄD%T# È=
T# ÉBT# Ë:T# ÌU ÎU ÏV4 Ï&VÐA8V4 Ò"VÓV4 ÔV(Ô#	T>Ô,T9Ô3T>Ô9T>ÕUÕUÕ	VÕ$VÖ VÖVÖVÖV4 ÖV%Ö(V1	Ö4A^×<AYÙ^Ù	Y8ÙY3Ù.^Ù3Y8Ù8^Ú^ Ú=[Û[%Û+^Û3?^
Ü2^Ü3^ Ý];Ý;^Þ
^Þ^ Þ&_&Þ8_	ß	_&ß_ ß
_&c                ó  — | �| dk(  ryt        | t        t        f«      rU| D �cg c]5  }t        |«      j	                  «       sŒt        |«      j	                  «       ‘Œ7 }}|rdj                  |«      S dS t        | «      S c c}w )uõ   Normalize ``deliver`` to its canonical comma-separated string; ``"local"`` when falsy.
    Lists/tuples (MCP clients, hand-edited jobs.json) are flattened â€” ``str(["telegram"])`` would
    yield ``"['telegram']"`` and fail resolution silently.r0   r%  rk  )r;   ÚlistÚtupler9   r=   rÌ   )Údeliverr  rY  s      rB   Ú_normalize_deliver_valuerâ  à  sn   € ð €˜' Rš-ØÜ�'œD¤%˜=Ô)Ø)0ÖC A´C¸³F·L±LµN”�Q“—‘•ÐCˆÐCÙ"'ˆs�x‰x˜‹Ð4¨WÐ4Üˆw‹<Ðùò Ds   £A?ÁA?Úallzbot-chatÚtuic                óÌ   — | xs dj                  «       }|j                  «       }|t        k(  ryt        dz   }|j                  |«      r|t	        |«      d j                  «       S y)u°   ``bot-chat[:<name>]`` â†’ ``""`` (own profile), the name, or ``None`` if not a bot-chat
    token. Token is case-insensitive; the name is normalized later by the profile layer.r0   r  N)r=   r:   r  rN  Úlen)ÚpartrA   Úloweredr’  s       rB   r)  r)  ÷  sb   € ð Š:�2×
Ñ
Ó
€CØ�i‰i‹k€GØÔ#Ò#ØÜ Ñ$€FØ×Ñ˜&Ô!Ø”3�v“;�<Ð ×&Ñ&Ó(Ð(ØrK   c                ó   — |s
t         dddœS 	 ddlm}m}  ||«      } ||«      s(t        j                  d| j                  dd«      |«       yt         |ddœS # t        $ r, t        j                  d	| j                  dd«      |d
¬«       Y yw xY w)u  Resolve a bot-chat token to a delivery target. ``""`` = own profile (no ``-p`` needed);
    otherwise the profile must exist locally â€” cross-machine delivery is intentionally unsupported
    so same-named profiles on other gateways can never be targeted by accident.r0   Nr   r   )Únormalize_profile_nameÚprofile_existsuV   Job '%s': bot-chat delivery profile '%s' not found on this machine â€” skipping targetrz   r‡   z1Job '%s': failed to resolve bot-chat profile '%s'Trä   )r  r  rê  rë  rr   rs   r8   r6   )rI   Úprofile_argrê  rë  Úcanons        rB   r*  r*    sœ   € ñ Ü-¸"È4ÑPÐPðßNÙ& {Ó3ˆÙ˜eÔ$Ü�N‰Nð.à—‘˜˜cÓ" Kô1ð Ü-¸%ÈdÑSÐSøÜò Ü�‰Ø?ÀÇÁÈÈsÓASÐU`Øð 	ô 	
ñ ðús   Ž?A Á	A Á2BÂBc                ó†   — | j                  «       t        vr| gS t        «       D �cg c]  }t        |«      sŒ|‘Œ c}S c c}w )z}Expand ``all`` to every home-target platform with a configured chat_id; non-tokens pass
    through as a single-element list.)r:   Ú_ROUTING_TOKENSr  rù   )rç  r  s     rB   Ú_expand_routing_tokensrð    s9   € ð ‡z�zƒ|œ?Ñ*ØˆvˆÜ2Ó4ÖT�!Ô8PÐQRÕ8SŠAÒTÐTùÒTs   ¦>·>©r]  c               ó†   — |r.| j                  d«      }|�t        |«      j                  «       r|S | j                  dd«      S )a  Raw deliver-lane value for a run outcome: the failure lane when ``for_failure`` and the job
    overrides it, else ``deliver``. Bookkeeping (outcome classification, unresolved-origin, incident
    'alerted' marking) must read the SAME lane the notice was routed through (NS-788).Úfailure_deliverrá  r%  )r8   r9   r=   )rI   r]  ró  s      rB   Ú_delivery_lane_valuerô  $  sC   € ñ ØŸ'™'Ð"3Ó4ˆØÐ&¬3¨Ó+?×+EÑ+EÔ+GØ"Ð"Ø�7‰7�9˜gÓ&Ð&rK   c          
     ó¶  — t        t        | |¬«      «      }|dk(  rg S i }g }|j                  d«      D �]"  }|j                  «       }|sŒ|j	                  «       t
        v }t        |«      D ]è  }t        | ||¬«      }|sŒ|d   j	                  «       t        |d   «      |j                  d«      f}	|j                  |	«      }
|
€|||	<   |j                  |«       Œot        j                  t        |j                  d«      xs d	«      d
«      t        j                  t        |
j                  d«      xs d	«      d
«      kD  sŒÕ|j                  d«      |
d<   Œê �Œ% |S )uÎ  Resolve auto-delivery targets from comma-separated ``deliver``; ``all`` expands to every
    platform with a home channel and combines with explicit targets. Dedup by (platform, chat_id,
    thread_id). ``for_failure=True`` (failure summaries, interrupted-run notices, drift/preflight
    alerts) resolves from ``failure_deliver`` INSTEAD when the job carries one â€”
    ``failure_deliver: local`` is the structural opt-out; absent, failures follow ``deliver``.rñ  r%  rk  r"  rF   rG   rW   rc   r0   r   )râ  rô  r+  r=   r:   rï  rð  r3  r9   r8   rË   Ú_MIRROR_PROVENANCE_RANK)rI   r]  rá  Úseenr  rA   r#  rç  rd   rÎ   rZ  s              rB   Ú_resolve_delivery_targetsrø  /  sY  € ô 'Ô';¸CÈ[Ô'YÓZ€GØ�'ÒØˆ	à€DØ€GØ�}‰}˜SÓ!ó FˆØ�i‰i‹kˆÙØØŸ™›¬Ð7ˆÜ*¨3Ó/ò 	FˆDÜ4°S¸$È~Ô^ˆFÙØØ˜*Ñ%×+Ñ+Ó-¬s°6¸)Ñ3DÓ/EÀvÇzÁzÐR]ÓG^Ð_ˆCØ—8‘8˜C“=ˆDØˆ|Ø"��S‘	Ø—‘˜vÕ&ô (×+Ñ+¬C°·
±
Ð;KÓ0LÒ0RÐPRÓ,SÐUVÓWÜ)×-Ñ-¬c°$·(±(Ð;KÓ2LÒ2RÐPRÓ.SÐUVÓWóXð *0¯©Ð4DÓ)E�Ð%Ò&ò	FðFð( €NrK   c                ó*   — t        | «      }|r|d   S dS )zAResolve the concrete auto-delivery target for a cron job, if any.r   N)rø  )rI   r  s     rB   Ú_resolve_delivery_targetrú  R  s   € ä'¨Ó,€GÙ ˆ7�1‰:Ð* dÐ*rK   >   ú.3gpú.aviú.mkvú.movú.mp4ú.webm>   ú.gifú.jpgú.pngú.jpegú.webpc                óN  — ddl m}m}m}	 ddlm}
 d|j                  dd«      i}g }|xs g D ��cg c]  \  }}t        |«      |f‘Œ }}}|j                  |«      }|D ��ch c]  \  }}|’Œ	 }}}|D ]'  \  }}	  |	|«      |v}|sŒ|j                  d|› �«       Œ) |�|nt        | d	d«      }|D ]î  \  }}	 t        j                  |«      j                  j                  «       } ||||¬
«      rd\  }}n!|t         v rd\  }}n|t"        v rd\  }}nd\  }} t        | |«      d||dœ||i¤Ž} |
||«      }|€t%        |d|› d�|«       |c S 	 |j'                  t)        j*                  «       ¬«      }|r+t        |dd«      st%        |d|› dt        |dd«      › �|«       Œð |S c c}}w c c}}w # t        $ r d}Y �Œ9w xY w# t,        $ r |j/                  «        ‚ w xY w# t        $ r>}t%        |d|› dt        |«      xs t1        |«      j2                  › �|«       Y d}~�Œqd}~ww xY w)zÑSend MEDIA files as native attachments (routed by extension, as in
    _process_message_background). Returns per-file error strings so a dropped attachment surfaces
    in run status, not just the gateway log.r   )ÚBasePlatformAdapterÚshould_send_media_as_audioÚvalidate_media_delivery_pathr‘   rz   r‡   Tz)attachment dropped by media path policy: NrF   )Úis_voice)Ú
send_voiceÚ
audio_path)Ú
send_videoÚ
video_path)Úsend_image_fileÚ
image_path)Úsend_documentÚ	file_path)rG   Úmetadatazcannot send media z: gateway loop unavailabler”   Úsuccesszmedia send failed for r�  r~  Úunknownzfailed to send media © )Úgateway.platforms.baser  r  r	  r—   r’   r8   r9   Úfilter_media_delivery_pathsr6   rË   r7   rQ   re  ró   r:   Ú_VIDEO_EXTSÚ_IMAGE_EXTSÚ_note_target_errorr˜   Ú_scriptÚ_get_media_send_timeoutÚTimeoutErrorÚcancelr¸  r¹  )r™   rG   Úmedia_filesr  rš   rI   rF   r  r  r	  r’   Újob_refÚerrorsr  ÚvÚ	requestedr  rZ  Úraw_pathÚ_vÚdroppedÚroute_platformÚ
media_pathÚ	_is_voiceÚextÚmethodÚpath_kwr�   rž   r˜   rv   s                                  rB   Ú_send_media_via_adapterr.  ]  s‘  € ÷Wñ Wå:Ø�S—W‘W˜T 3Ó'Ð(€GØ€FØ*5Ò*;¸×=¡  A”#�a“&˜!’Ð=€IÑ=Ø%×AÑAÀ+ÓN€Kà%×&‘$�!�QŠAÐ&€DÑ&Ø!ò R‰ˆ�"ð	Ù2°8Ó<ÀDÐHˆGò Ø�M‰MÐEÀhÀZÐPÕQðRð "*Ð!5‘X¼7À7ÈJÐX\Ó;]€NØ!,ò !eÑˆ
�Ið 	eÜ—+‘+˜jÓ)×0Ñ0×6Ñ6Ó8ˆCÙ)¨.¸#È	ÕRØ"<‘�™ØœÑ#Ø"<‘�™ØœÑ#Ø"A‘�™à">‘�˜Ø+”7˜7 FÓ+ð MØ¨(ñMØ7>À
Ð6KñMˆDá-¨d°DÓ9ˆFØˆ~Ü"ØÐ1°*°Ð=WÐXÐZ`ôbà’ðàŸ™¬w×/NÑ/NÓ/P˜ÓQ�ñ œg f¨i¸Ô>Ü"ØØ,¨Z¨L¸¼7À6È7ÐT]Ó;^Ð:_Ð`Øôøð3!eðD €Mùó_ >ùó 'øô ò 	Ø‹Gð	ûô6  ò Ø—‘”Øðûô ò 	eäØÐ0°°¸B¼sÀ1»vÒ?YÌÈaË×IYÑIYÐ>ZÐ[Ð]c÷eò eûð	eúsN   °F!Á F'Á8
F-Â5BGÅ$F?Å0-GÆ-F<Æ;F<Æ?GÇGÇ	H$Ç&3HÈH$c                ó`   — t        | t        «      r| j                  ||«      S t        | ||«      S )zXRead ``key`` from a SendResult-like object or the plain dict the silence filter returns.)r;   r<   r8   r7   )Úsend_resultrÎ   r�  s      rB   Ú_result_fieldr1  š  s,   € ä�+œtÔ$Ø�‰˜s GÓ,Ð,Ü�;  WÓ-Ð-rK   c                ó  — | €yt        | t        «      rd| v }nt        | d«      }|rt        t	        | d«      «      syt	        | d«      du ryt	        | d«      €5t	        | d«      s)t
        j                  d|«       |�|j                  d«       y)uç  Return True only if ``send_result`` unambiguously confirms delivery. ``None`` or no
    ``success`` attr/key is NOT success (would log "delivered" while nothing was sent).
    ``delivered is False`` REJECTS even with truthy ``success`` (the silence-narration filter
    returns ``{"success": True, "delivered": False}``). No ``message_id``/``raw_response`` is still
    accepted (some adapters return a bare success) but logged at WARNING as UNVERIFIED.

    A live adapter that returns ``None`` (e.g. a swallowed exception, a busy platform, or a code path that
    returns early without producing a ``SendResult``) must NOT be treated as success â€” doing so causes the
    scheduler to log ``"delivered to <chat> via live adapter"`` while the gateway never actually sees the
    message (#47056).
    * No ``message_id`` and no ``raw_response`` means we have no positive evidence of a send. Telegram
    ``SendResult`` objects carry ``message_id``; the dict-filter shape does not. See #77763.
    Fr  Ú	deliveredÚ
message_idÚraw_responseu‹   Job '%s': live adapter reported success with no delivery evidence (no message_id, no raw_response) â€” treating as delivered but UNVERIFIEDT)r;   r<   ÚhasattrrP   r1  rr   rs   rË   )r0  r‡  Ú
unverifiedÚhas_successs       rB   Ú_confirm_adapter_deliveryr9  ¡  s™   € ð ÐØÜ�+œtÔ$Ø ;Ð.‰ä˜k¨9Ó5ˆÙœd¤=°¸iÓ#HÔIØÜ�[ +Ó.°%Ñ7Øä�k <Ó0Ð8Ü˜k¨>Ô:ä�‰ðð ô		ð
 Ð!Ø×Ñ˜dÔ#ØrK   c                ó¼  — t        t        | «      dd«      }t        |«      sy	 ddlm}  || t        |«      «      } |||«      }|€y|j                  d¬«      }t        |t        «      xr/ t        |j                  d«      xs d«      j                  «       dk(  }	|	rt        j                  d||«       |	S # t        $ r t        j                  d||d	¬
«       Y yw xY w)uÂ  Is an ambiguous ``telegram:<positive_chat_id>:<numeric_thread_id>`` target a channel
    Direct-Messages topic (``direct_messages_topic_id``) rather than a private-chat forum topic
    (``message_thread_id``)? Shape cannot decide; signal is ``get_chat_info`` type == ``channel``.
    Fails SAFE to False (thread routing) without a probe or on any probe error/timeout.

    Callers gate this on the ambiguous shape first (``telegram:<positive_chat_id>:<numeric_thread_id>``) â€”
    that shape is identical for both cases, so shape alone cannot decide (this was the #52060 regression).
    Probe the live adapter's ``get_chat_info`` once and only return True when the chat is a channel.
    See #22773.
    Úget_chat_infoNFr   r‘   é
   r”   u\   Job '%s': get_chat_info probe failed for chat=%s â€” defaulting to message_thread_id routingTrä   r¸  r0   ÚchanneluG   Job '%s': chat=%s is a channel â€” routing via direct_messages_topic_id)r7   r¸  r–   r—   r’   r9   r˜   r6   rr   rŠ   r;   r<   r8   r:   r‰   )
Úruntime_adapterrG   rš   r‡  r;  r’   r�   rž   r‰   Ú
is_channels
             rB   Ú_is_channel_dm_topicr@  È  så   € ô œD Ó1°?ÀDÓI€MÜ�MÔ"ØðÝ>Ù˜_¬c°'«lÓ;ˆÙ)¨$°Ó5ˆØˆ>Øà�}‰} Rˆ}Ó(ˆô ˜D¤$Ó'Ò\¬C°·±¸Ó0@Ò0FÀBÓ,G×,MÑ,MÓ,OÐS\Ñ,\€JÙÜ�‰ØUØ�Gô	ð Ðøô ò Ü�‰ð6à�G dð 	ô 	,ñ ðús   ¤#B6 ÁB6 Â6"CÃCc                óà   — 	 | xs i j                  d«      }t        |t        «      r|j                  d«      nd}t        |t        «       xs |j                  dd«      duS # t        $ r Y yw xY w)z®Resolve ``cron.delivery.notify`` (default True). Only an explicit ``False`` disables; a
    missing/malformed section keeps the default so a typo cannot silently mute briefs.rN   ÚdeliveryNÚnotifyTF)r8   r;   r<   r6   )rS   Úcron_cfgÚdelivery_cfgs      rB   Ú_cron_delivery_notify_enabledrF  î  sn   € ðØ’I˜2—?‘? 6Ó*ˆÜ3=¸hÌÔ3M�x—|‘| JÔ/ÐSWˆÜ˜l¬DÓ1Ð1Òb°\×5EÑ5EÀhÐPTÓ5UÐ]bÐ5bÐbøÜò Ùðús   ‚AA! Á!	A-Á,A-c                óú  — t        |«      xs d}| j                  di «      j                  «       D ��ci c]  \  }}|d   dv r||“Œ c}}xs d}||dœj                  «       D ��ci c]   \  }}| j                  |«      xs d|k7  r||“Œ" }}}|sy| j                  |«       	 ddlm}	  |	| d   |«       yc c}}w c c}}w # t        $ r0}
t        j                  d	| j                  d«      |
«       Y d}
~
yd}
~
ww xY w)
zÌPersist ``last_delivery_unverified``: list of ``platform:chat_id`` targets acked with no
    evidence, or None, alongside queued Bot Chat receipts. Never raises (bookkeeping must not fail a
    delivery).Nru  rr  r{  )Úlast_delivery_unverifiedÚlast_delivery_queuedr   )Ú
update_jobrz   z4Job '%s': could not record delivery verification: %s)	rß  r8   ÚitemsÚupdateÚ	cron.jobsrJ  r6   rr   rŠ   )rI   Úunverified_targetsÚ	new_valuerd   rÈ  r|  rÎ   rÏ   ÚvaluesrJ  rÍ  s              rB   Ú_record_delivery_verificationrQ  ù  s  € ô Ð'Ó(Ò0¨D€Ià�g‰gÐ3°RÓ8×>Ñ>Ó@÷=¡/ &¨'à˜Ñ"Ð&;Ñ;ð �g‰oó =ò Eà@Dð ð %.Àvñ,ç�eƒg÷2™Z˜S %à—'‘'˜#“,Ò& $¨5Ò0ð �5‰jð 2€Fñ 2ñ ØØ‡J�JˆvÔðaÝ(Ù�3�t‘9˜fÕ%ùó=ùó2øô ò aÜ�‰ÐKÈSÏWÉWÐUYË]Ð\_×`Ñ`ûðaús#   ³B5Á%%B;Â"C Ã	C:Ã
&C5Ã5C:c                  ó  — e Zd ZU dZded<   ded<   ded<   ded<   d	ed
<   ded<   ded<   ded<   ded<   ded<   ded<   ded<   ded<   ded<   d	ed<   ded<   ded<   ded<   ded<   ded<   d	ed<   dZded<   ed!d„«       Zed"d„«       Zy )#Ú_TargetDeliveryzJPer-target delivery state shared by the live-adapter and standalone lanes.r<   rI   r   rF   r9   rX   rG   úOptional[str]rW   Ú	transportr>   r>  Útarget_adaptersÚconfigrš   rP   Únotify_deliveryrE   Úorigin_targetÚorigin_user_idÚis_dm_targetr‹   Úmirror_this_targetÚin_channel_surfaceÚinchannel_continuableÚopened_thread_idFÚlive_adapter_readyc                óN   — | j                   d uxr | j                   j                  S ©N)rU  Úis_relay©Úselfs    rB   rc  z_TargetDelivery.is_relay)  s    € à�~‰~ TÐ)ÒE¨d¯n©n×.EÑ.EÐErK   c                ó8   — | j                   › d| j                  › �S )Nr  )rX   rG   rd  s    rB   Úwherez_TargetDelivery.where-  s   € à×$Ñ$Ð% Q t§|¡| nÐ5Ð5rK   N)rï   rP   ©rï   r9   )	r¹  Ú
__module__Ú__qualname__Ú__doc__Ú__annotations__r`  Úpropertyrc  rg  r  rK   rB   rS  rS    s®   … áTà	ƒIØƒMØÓØƒLØÓØƒNØƒLØÓØÓØƒKØ
ƒIØÓØƒLØÓØ!Ó!ØÓØÓØÓØÓØÓØ#Ó#Ø$Ð˜Ó$àòFó ðFð ò6ó ñ6rK   rS  c                óZ   — t         j                  d| d   |«       |j                  |«       y)zKLog a per-target delivery failure as a WARNING and record it in ``errors``.rƒ  rz   N)rr   rs   rË   )rI   r…  r"  s      rB   r  r  2  s"   € ä
‡N�N�> 3 t¡9¨cÔ2Ø
‡M�M�#ÕrK   c                ór   — |rt         j                  d| d   |«       yt         j                  d| d   |«       y)zPRelay targets have no standalone fallback, so the log line must not promise one.rƒ  rz   ú(Job '%s': %s, falling back to standaloneNr„  )rI   r…  rc  s      rB   Ú_warn_live_lane_failurerq  8  s.   € áÜ�‰�~ s¨4¡y°#Õ6ä�‰ÐAÀ3ÀtÁ9ÈcÕRrK   c                óD  — ddl m}m} |}d}	t        |t        j
                  «      r`|j                  ||«      }
|
�||
ini }|
�Dddlm} ddl	m
} |j                  j                  |«      } ||
|�
 ||d¬«      n |d¬«      |«      }	|	€
 ||||«      }	|	�|	j                  }|	j                  }n4ddlm} | |«       v rdd	|› d
�fS |j                  j                  |«      }d}|	� |	j                   s|€|€&ddl	m
}  |d¬«      }n|r|j"                  sdd	|› d�fS |	|||fdfS )zËResolve ``(transport, pconfig, runtime_adapter, target_adapters)`` for one target, or
    ``(None, error)`` when it cannot be served (relay-fronted with no live transport, or not
    configured/enabled).r   )ÚDeliveryTransportÚresolve_delivery_transportN)rÊ   )ÚPlatformConfigTr   r  z
platform 'z’' is relay-fronted and has no live gateway transport; start the gateway (its ticker owns relay-fronted delivery and will fire the job on schedule)z' not configured/enabled)Úgateway.deliveryrs  rt  r;   Ú
_preflightÚSharedRouteAdaptersr8   ÚdataclassesrÊ   r¬   ru  Ú	platformsrW  r™   r  r  rc  r€   )rI   rF   rX   rd   ÚadaptersrW  rs  rt  rV  rU  ÚsharedrÊ   ru  Úownr>   r>  r  s                    rB   Ú_resolve_target_transportr~  @  sd  € ÷
 OØ€OØ€IÜ�(œJ×:Ñ:Ô;ð —‘˜h¨Ó/ˆØ06Ð0B˜8 VÑ,ÈˆØÐõ
 ,Ý5Ø×"Ñ"×&Ñ& xÓ0ˆCÙ)Ø°c°o™ ¨TÕ2É>ÐbfÔKgØóˆIð ÐÙ.¨x¸ÀÓQˆ	ØÐØ×"Ñ"ˆØ#×+Ñ+‰õ 	:ØÑ3Ó5Ñ5ØØ˜]˜Oð ,ð ðð ð ×"Ñ"×&Ñ& xÓ0ˆØˆàÐ )×"4Ò"4¸¸ð
 ˆ?Ý5Ù$¨TÔ2‰GÙ˜GŸOšOØ�z - Ð0HÐIÐIÐIØ�w °ÐAÀ4ÐGÐGrK   c                ó    — t        | dd«      }t        |«      r	 t         ||«      «      S t        t        | dd«      «      S # t        $ r Y yw xY w)a  D6 probe: can this adapter deliver a continuable in_channel brief on ``platform_name``?
    Per-platform check first (one RelayAdapter fronts N platforms; the scalar attr only carries
    the PRIMARY identity's bit); native adapters use the class attribute.Ú+supports_inchannel_continuable_for_platformNFÚsupports_inchannel_continuable)r7   r–   rP   r6   )r>  rX   Úper_platform_checks      rB   Ú_inchannel_surface_supportedrƒ  y  sb   € ô !ØÐFÈóNÐäÐ"Ô#ð	ÜÑ*¨=Ó9Ó:Ð:ô ”˜Ð)IÈ5ÓQÓRÐRøô ò 	Ùð	ús   šA Á	AÁAc                ó.  — ddl m} ddlm}m} | j
                  }| j                  }| j                  |j                  k(  xr4 |duxr.  |t        | j                  «      «      xr  |t        |«      «      }|rft        | j                  | j                  | j                  |d   «      r7d}t        |«      |d   | j                  dœ}t        |«      | j                  dœ}	n=|�t        |«      nd}|d   | j                  dœ}|r||d	<   d
| j                  i}	|r||	d	<   | j                  rk| j                   j#                  d«      rP|j%                  dt        | j                   d   «      «       |	j%                  dt        | j                   d   «      «       |||	fS )uv  Compute ``(route_thread_id, route_metadata, media_metadata)`` for a live send, ONCE so text
    and media agree. ``telegram:<positive_chat_id>:<numeric_thread_id>`` is ambiguous (private
    forum topic vs channel DM topic need OPPOSITE routing) â€” see ``_is_channel_dm_topic``.
    ``thread_id`` rides in ``route_metadata`` to bypass the router's private-chat anchor rule.r   r¤   )Ú_looks_like_intÚ#looks_like_telegram_private_chat_idNrz   )Údirect_messages_topic_idr‡  rC  )r‡  rC  )r‡  rC  rW   rC  rª   )r¬   r¥   rv  r…  r†  rI   rW   rF   ÚTELEGRAMr9   rG   r@  r>  rš   rX  rY  rE   r8   r¥  )
Útr¥   r…  r†  rI   rW   Úis_ambiguous_telegram_topicÚroute_thread_idÚroute_metadataÚmedia_metadatas
             rB   Ú_live_route_metadatarŽ  ‡  s|  € õ
 (ßUØ
�%‰%€CØ—‘€Ià	�
‰
�h×'Ñ'Ñ'ò 	,Ø˜TÐ!ò	,á/´°A·I±I³Ó?ò	,ñ œC 	›NÓ+ð	  ñ #Ô';Ø	×Ñ˜1Ÿ9™9 a§f¡f¨c°$©iô(9ð ˆä(+¨I«À#ÀdÁ)Ø×'Ñ'ñ
ˆô 7:¸)³nÐPQ×PaÑPaÑb‰ð -6Ð,Aœ#˜iœ.ÀtˆØ$'¨¡I¸×9JÑ9JÑKˆÙØ*9ˆN˜;Ñ'Ø" A×$5Ñ$5Ð6ˆÙØ*3ˆN˜;Ñ'ð
 	‡‚˜1Ÿ8™8Ÿ<™<¨
Ô3Ø×!Ñ! *¬c°!·(±(¸:Ñ2FÓ.GÔHØ×!Ñ! *¬c°!·(±(¸:Ñ2FÓ.GÔHØ˜N¨NÐ:Ð:rK   c               óh  — ddl m} ddlm}m}	 | j
                  }
 || j                  | j                  «      } |	| j                  t        | j                  «      |d¬«      } ||j                  |||| j                  ¬«      | j                  «      }|€|j                  d«       y		 |j                  d
¬«      }t/        |d«      }t/        |d«      }g }t1        ||
d   |«      }|r|r|j                  | j$                  «       |s¤|€d\  }}n]t3        |t4        «      r+|j7                  d«      xs |j7                  d«      xs d}d}n"t9        |dd«      t;        |«      j<                  }}d| j$                  › d|› d|› d�}t?        |
|| j@                  «       |j                  |«       y	|rZ| jB                  rN|j7                  d«      r=|j7                  d«      xs | jB                  }tE        |
d|› d | j$                  › d!�|«       dd"|fS # t         $ r |j#                  «       r=d| j$                  › d�}t&        j)                  d|
d   |«       |j                  |«       Y y	t&        j)                  d|
d   | j*                  | j                  «       Y yt,        $ r}|j                  d|› �«       ‚ d}~ww xY w)#z§Schedule the text send on the gateway loop; returns ``(adapter_ok, timed_out, message_id)``.
    Re-raises a real send error so the caller falls through to standalone.r   r‘   )ÚDeliveryRouterÚDeliveryTargetT)rF   rG   rW   Úis_explicit)rU  Nz)live adapter event loop scheduling failed)FFNr=  r”   zlive adapter send to z. timed out before the coroutine was dispatchedrp  rz   zžJob '%s': live adapter send to %s:%s timed out after 60s; already dispatched (in flight), assuming delivered (skipping standalone fallback to avoid duplicate))TTNzlive adapter send failed: r5  r4  )zno response from adapterÚNoner~  Úfilteredr  r<   z returned unconfirmed result (z, error=r  Úthread_fallbackÚrequested_thread_idzconfigured thread_id z for z+ was not found; delivered without thread_idF)#r—   r’   rv  r�  r‘  rI   rW  rV  rF   r9   rG   Ú_deliver_to_platformrU  rš   rË   r˜   r  r  rg  rr   rs   rX   r6   r1  r9  r;   r<   r8   r7   r¸  r¹  rq  rc  rW   r  )r‰  Útext_to_sendr‹  rŒ  Útarget_errorsÚdelivery_errorsrN  r’   r�  r‘  rI   ÚrouterÚroute_targetrž   r0  r…  ÚexÚsend_raw_responseÚdelivered_message_idÚ_evidence_gapÚsend_successrW  Úshaper–  s                           rB   Ú_live_send_textr£  ·  s®  € õ ;ß?Ø
�%‰%€CÙ˜AŸH™H a×&7Ñ&7Ó8€FÙ!Ø—‘¤S¨¯©£^¸Ð\`ôb€Lñ &Ø×#Ñ#Ø˜,¨À!Ç+Á+ð 	$ó 	OØPQ×PVÑPVóX€Fð €~Ø×ÑÐHÔIØ!ðØ—m‘m¨B�mÓ/ˆô0 & k°>ÓBÐÜ(¨°lÓCÐØ€MÜ,¨[¸#¸d¹)À]ÓS€LÙ™Ø×!Ñ! !§'¡'Ô*áØÐØ;‰JˆC‘Ü˜¤TÔ*à—/‘/ 'Ó*ÒV¨k¯o©o¸jÓ.IÒVÈYˆCØ‰Eä  ¨g°tÓ<¼dÀ;Ó>O×>XÑ>X�ˆCØ% a§g¡g YÐ.LÈUÈGÐS[Ð\_Ð[`Ð`aÐbˆÜ  S¨!¯*©*Ô5Ø×Ñ˜SÔ!Ø!Ù˜QŸ[š[Ð->×-BÑ-BÐCTÔ-UØ/×3Ñ3Ð4IÓJÒYÈaÏkÉkÐÜØØ#Ð$7Ð#8¸Ø�w‰wˆiÐBðDàô		ð
 �Ð,Ð,Ð,øôe ò  ð �=‰=Œ?Ø)¨!¯'©'¨Ð2`ÐaˆCÜ�N‰NÐEÀsÈ4ÁyÐRUÔVØ× Ñ  Ô%Ù%Ü�‰ð"ð �‰I�q—‘¨¯	©	ô	3ñ  Üò à×ÑÐ9¸"¸Ð>Ô?Øûðús%   Â&H ÈAJ1É/J1ÊJ1ÊJ,Ê,J1c           	     ó8  — t        |xs i «      }| j                  r�| j                  j                  |d<   | j                  j                  | j                  «      }|�O|j                  | j                  k(  r6|j                  r|j                  |d<   |j                  r|j                  |d<   t        | j                  | j                  ||xs d| j                  | j                  | j                  ¬«      }|D ]#  }|j                  |› d| j                  › d�«       Œ% y)zRSend extracted media as native attachments with the same routing as the text send.Ú_relay_logical_platformNrk   rª   )rF   ú	 (target r  )r<   rc  rF   rÏ   rW  ræ   rG   rk   rª   r.  r>  rš   rI   rË   rg  )r‰  r�  r   rš  Úrouted_media_metadataÚlogical_homeÚ_media_errorsÚ_mes           rB   Ú_live_send_mediar«    s   € ô ! Ò!5°2Ó6ÐØ‡z‚zØ;<¿:¹:×;KÑ;KÐÐ7Ñ8Ø—x‘x×0Ñ0°·±Ó<ˆØÐ#¨×(<Ñ(<ÀÇ	Á	Ò(IØ×#Ò#Ø3?×3GÑ3GÐ% iÑ0Ø×$Ò$Ø4@×4IÑ4IÐ% jÑ1Ü+Ø	×Ñ˜1Ÿ9™9 kÐ3HÒ3PÈDÐRS×RXÑRXÐZ[×Z_ÑZ_Ø—‘ô€Mð
 ò <ˆØ×Ñ #  i°·±¨y¸Ð:Õ;ñ<rK   c                ó�  — | j                   }| j                  }t        |j                  d«      | j                  |j                  d«      ¬«      }d}d}| j
                  rEt        || j                  | j                  | j                  | j
                  | j                  fi |¤Ž d}| j                  rÈ| j                  r¼|sºt        || j                  | j                  | j                  | j                  fd| j                  i|¤Ž}|s/t        j!                  d|d   | j                  | j                  «       |rºt        || j                  | j                  | j                  t#        |«      | j                  fi |¤Ž nw| j                  rk| j                  s_t        j!                  d	|d   | j                  | j                  |j                  d
«      |j                  d«      |j                  d«      «       t%        || j                  | j                  | j                  | j&                  | j                  | j(                  xr | xr | ¬«       y)zµAfter a confirmed live send, seed continuation session(s) and run the generic mirror.
    Thread seeding is deferred here so open-succeeds/deliver-fails never seeds an unseen brief.r¨   rª   )r¨   rj   rª   FTrk   uY   Job '%s': in_channel seed did NOT land on %s:%s â€” a plain reply will not see this briefrz   uö   Job '%s': in_channel delivery to %s:%s is not a continuable target (origin=%s:%s thread=%s; not the origin conversation, and not a mirror-eligible fallback/opted-in target the seed can key) â€” seed skipped; the plain mirror below may still applyrF   rG   rW   ©rW   rk   r€   N)rI   rE   r<   r8   r[  r_  r½   r>  rX   rG   r‹   r]  r^  r¿   rZ  rr   rs   r9   r�   rW   r\  )r‰  rŸ  rI   rE   Úseed_kwargsÚthread_seededÚinchannel_seededs          rB   Ú_seed_live_delivery_sessionsr±    sð  € ð �%‰%€CØ�X‰X€FÜØ—*‘*˜[Ó)°·±È&Ï*É*ÐU_ÓJ`ôb€Kà€MØÐØ×ÒÜ!Ø�×"Ñ" A§O¡O°Q·Y±YÀ×@RÑ@RÐTU×TaÑTañ	
àò	
ð ˆð 	×Ò × 7Ò 7ÁÜ5Ø�×"Ñ" A§O¡O°Q·Y±YÀÇÁñ5à×$Ñ$ð5à(3ñ5Ðñ  Ü�N‰Nð<à�D‘	˜1Ÿ?™?¨A¯I©Iô7ñ  Ü%Ø�Q×&Ñ&¨¯©¸¿¹ÄCÐH\ÓD]Ø—‘ñð óð 
×	Ò	 a×&=Ò&=Ü�‰ð>ð
 �‰I�q—‘¨¯	©	Ø�J‰J�zÓ" F§J¡J¨yÓ$9¸6¿:¹:ÀkÓ;Rô	Tô  ØˆQ�_‰_˜aŸi™i¨¯©À!Ç+Á+Ø× Ñ Ø×$Ñ$ÒS¨]Ð):ÒSÐCSÐ?SöUrK   c          	     ó¼  ‡— | j                   }t        | «      \  }}}	d}
	 |j                  «       }d\  }}}|s|st        |d| j                  › �|«       d}n|rt        | ||||||¬«      \  }}}|r|s|rt        | |	||«       n*|r(|r&t        |t        |«      › d| j                  › d�|«       |rGt        j                  d|d   | j                  | j                  |�|nd
|�|nd
«       d}
t        | |«       |
S # t        $ rY}d| j                  › d|› �Št        ˆfd„|D «       «      s|j                  ‰«       t!        |‰| j"                  «       Y d	}~|
S d	}~ww xY w)a  Deliver one target via the live gateway adapter; True once delivered. ``target_errors`` =
    this lane's soft failures (surfaced only if standalone also fails); ``delivery_errors`` =
    partial failures (media, thread fallback) that surface even on success.F)TFNz8live adapter send skipped (empty text and no media) for ©r™  rš  rN  z& media attachment(s) not delivered to z& (live adapter confirmation timed out)zEJob '%s': delivered to %s:%s via live adapter thread=%s message_id=%srz   NÚ-Tzlive adapter delivery to ú	 failed: c              3  ó&   •K  — | ]  }‰|v –— Œ
 y ­wrb  r  )rP  rW  Úerr_msgs     €rB   rR  z,_deliver_via_live_adapter.<locals>.<genexpr>†  s   øè ø€ Ò; c�7˜c”>Ñ;ùs   ƒ)rI   rŽ  r=   r  rg  r£  r«  ræ  rr   r‰   rX   rG   r±  r6   ÚanyrË   rq  rc  )r‰  Úcleaned_textr   r™  rš  rN  rI   r‹  rŒ  r�  r3  r˜  Ú
adapter_okÚ	timed_outrŸ  rv   r·  s                   @rB   Ú_deliver_via_live_adapterr¼  K  s˜  ø€ ð �%‰%€CÜ6JÈ1Ó6MÑ3€O�^ ^Ø€Ið3:ð $×)Ñ)Ó+ˆØ6GÑ3ˆ
�IÐ3Ù¡KäØÐOÐPQ×PWÑPWÈyÐYØôð ‰JÙÜ:IØ�< °.Ø+¸_Ø#5ô;Ñ7ˆJ˜	Ð#7ñ ™i©KÜ˜Q °¸_ÕMÙ™;ÜØÜ�{Ó#Ð$Ð$JØ—7‘7�)ÐAðCàô	!ñ ä�K‰Kð XØ�D‘	˜1Ÿ?™?¨A¯I©IØ#2Ð#>‘ÀCØ(<Ð(HÑ$ÈcôSð ˆIÜ(¨Ð,@ÔAð Ðøô ò :Ø-¨a¯g©g¨Y°iÀ¸sÐCˆÜÓ;¨]Ô;Ô;Ø× Ñ  Ô)Ü  W¨a¯j©j×9Ð9ØÐûð:ús    CC9 Ã9	EÄAEÅEc                ób  ‡ ‡‡‡‡‡— ddl mŠ ‰ j                  Šd‰ j                  › d�}t	        «       Šˆˆˆˆˆ fd„}dˆfd„}dˆˆ fd„}t        j                  «       r ||«      S ‰j                  «       s‰s |d‰ j                  › �«      S  |«       }	 t        j                  |«      d	fS # t        $ r4 d
‰ j                  › d‰› d�}t        j                  d‰d   |«       d	|fcY S t        $ �r%}	|j                  «        t        j                  |	«      r ||«      cY d	}	~	S 	 t        j                   j#                  d¬«      }
	 |
j%                  t'        j(                  «       j                  t        j                   |«       «      j+                  d¬«      d	f|
j-                  d¬«       cY d	}	~	S # |
j-                  d¬«       w xY w# t.        $ r>}t        j                  |«      r ||«      cY d	}~cY d	}	~	S  ||«      cY d	}~cY d	}	~	S d	}~ww xY wd	}	~	wt.        $ r} ||«      cY d	}~S d	}~ww xY w)u§   Run the standalone sender for one target: ``(result, None)`` or ``(None, error)`` (already
    logged â€” WARNING for a shutdown race, ERROR with traceback otherwise).r   )Ú_send_to_platformúdelivery to u)    skipped â€” interpreter is shutting downc            
   “  ó¶   •K  — t        j                   ‰ ‰j                  ‰j                  ‰j                  ‰‰j
                  ‰¬«      ‰¬«      ƒ d {  –—† S 7 Œ­w)N)rW   r   r”   )ÚasyncioÚwait_forrF   r>   rG   rW   )r¾  rÁ  r   Úsend_timeoutr‰  s   €€€€€rB   Ú_sendz_standalone_send.<locals>._send–  sO   øè ø€ ô ×%Ñ%Ñ&7Ø�J‰J˜Ÿ	™	 1§9¡9¨gÀÇÁØ#ô'%à.:ô<÷ <ð 	<ð <ús   ƒAAÁAÁAc                ó@   •— t         j                  d‰d   | «       d | fS )Nrƒ  rz   r„  )r…  rI   s    €rB   Ú_warnedz!_standalone_send.<locals>._warned�  s!   ø€ Ü�‰�~ s¨4¡y°#Ô6Ø�SˆyÐrK   c                óh   •— d‰j                   › d| › �}t        j                  d‰d   |d¬«       d |fS )Nr¿  rµ  rƒ  rz   Trä   )rg  rr   r~  )rv   r…  rI   r‰  s     €€rB   Ú_failedz!_standalone_send.<locals>._failed¡  s;   ø€ Ø˜QŸW™W˜I Y¨q¨cÐ2ˆÜ�‰�^ S¨¡Y°¸dˆÔCØ�SˆyÐrK   z6standalone send skipped (empty text and no media) for Nzstandalone send to z timed out after z#s (the send may still be in flight)rƒ  rz   r]   )Úmax_workersr“   r”   F)Úwait)r…  r9   rï   útuple[None, str])rï   rË  )r,  r¾  rI   rg  r>  rQ   Ú_interpreter_shutting_downr=   rÁ  Úrunr  rr   r~  ÚRuntimeErrorÚcloseÚ
concurrentÚfuturesÚThreadPoolExecutorÚsubmitÚcontextvarsÚcopy_contextr˜   Úshutdownr6   )r‰  rÁ  r   Úshutdown_msgrÄ  rÆ  rÈ  r�   r…  Úrun_errÚpoolrv   r¾  rI   rÃ  s   ```         @@@rB   Ú_standalone_sendrÚ  Œ  sï  ý€ õ :Ø
�%‰%€CØ! !§'¡' Ð*SÐT€Lä/Ó1€L÷<ð <õöô ×(Ñ(Ô*Ù�|Ó$Ð$ð �=‰=Œ?¡;ÙÐOÐPQ×PWÑPWÈyÐYÓZÐZÙ‹7€DðÜ�{‰{˜4Ó  $Ð&Ð&øÜò ð % Q§W¡W IÐ->¸|¸nð M3ð 3ˆä�‰�^ S¨¡Y°Ô4Ø�SˆyÒÜó à�
‰
ŒÜ×,Ñ,¨WÔ5Ù˜<Ó(Õ(ð	Ü×%Ñ%×8Ñ8ÀQÐ8ÓGˆDð*ð —{‘{¤;×#;Ñ#;Ó#=×#AÑ#AÄ7Ç;Á;ÑPUÓPWÓX×_Ñ_Øð `ó  Ø!%ð&ð —‘ 5�×)Ò)ø�—‘ 5�Õ)ûÜò 	Ü×0Ñ0°Ô3Ù˜|Ó,×,Ò,Ù˜1“:×Òûð	þô ò Ù�q‹zÕûðús�   ÂB+ Â+:H.Ã'	H.Ã0,HÄH.Ä# GÅAF/ÆGÆ)H.Æ/GÇGÇ	HÇHÇ+HÇ,HÇ0H.Ç6HÇ=HÇ>HÈH.ÈHÈHÈH.ÈH)È#H.È)H.c           	     ó\  — | j                   }| j                  r3|s|j                  d| j                  › d�«       |j	                  |«       yt        | ||«      \  }}|€C|rA|j                  d«      r0d|d   › d| j                  › d�}t        j                  d|d	   |«       |�#|j                  |«       |j	                  |«       yt        |t        «      r|j                  d
«      ndxs g D ]@  }d|› d| j                  › d�}	t        j                  d|d	   |	«       |j                  |	«       ŒB t        j                  d|d	   | j                  | j                  «       t        || j                  | j                  | j                  | j                   | j"                  | j$                  ¬«       y)z?Standalone fallback for a target the live lane did not deliver.zrelay delivery to z failedNr~  zdelivery error: r¦  r  rƒ  rz   Úwarningszdelivery warning: zJob '%s': delivered to %s:%sr­  )rI   rc  rË   rg  ÚextendrÚ  r8   rr   r~  r;   r<   r‰   rX   rG   r�   r‹   rW   rZ  r\  )
r‰  rÁ  r   r™  rš  rI   r˜   rW  Ú_wr…  s
             rB   Ú_deliver_standalonerß  Ï  sx  € ð �%‰%€CØ‡z‚záØ× Ñ Ð#5°a·g±g°Y¸gÐ!FÔGØ×Ñ˜}Ô-ØÜ" 1 g¨{Ó;�K€FˆCØ
€{‘v &§*¡*¨WÔ"5à  ¨¡Ð 1°¸1¿7¹7¸)À1ÐEˆÜ�‰�^ S¨¡Y°Ô4Ø
€Ø×Ñ˜SÔ!Ø×Ñ˜}Ô-Øô *4°F¼DÔ)Aˆv�z‰z˜*Ô%ÀtÒRÐPRò $ˆØ" 2 $ i°·±¨y¸Ð:ˆÜ�‰�^ S¨¡Y°Ô4Ø×Ñ˜sÕ#ð$ô ‡K�KÐ.°°D±	¸1¿?¹?ÈAÏIÉIÔVäØˆQ�_‰_˜aŸi™i¨¯©À!Ç+Á+Ø× Ñ Ø×$Ñ$ö&rK   c          	     óâ  — ddl m}	 |d   }
|d   }|j                  d«      }t        | «      xs i }|j                  d«      }|r/|s-t        j                  d| d   || j                  dd	«      |«       n|rt        j                  d
| d   |
||«       t        ||
||«      }|xr t        | |||¬«      }|r|j                  d«      nd}t        |j                  d«      xs d«      j                  «       }|dk(  xs | xr t        |«      j                  d«      }|xs |xr t        ||¬«      }	  |	|
j                  «       «      }t!        | ||
|||«      \  }}|€t        | ||«       y|\  }}}}|duxr |duxr  t#        |dd„ «      «       }t%        ||
«      dk(  }|r7|�5t'        ||
«      s)t        j                  d| j                  dd«      |
«       d}|r|r|rd}d}|r|s|�|�|st)        | |||«      xs d}|r|}t+        d.i d| “d|“d|
“d|“d|“d|“d|“d|“d |“d!|“d"|“d#|“d$|“d%|“d&|“d'|“d(|“d)|“d*|“d+|“d,|“d-|“ŽS # t        t        f$ r t        | d|
› d�|«       Y yw xY w)/z·Per-target prologue of ``_deliver_result``: origin/mirror/in_channel gates, transport
    resolution, continuable-thread open. None (error noted in ``delivery_errors``) if unservable.r   r¤   rF   rG   rW   zUJob '%s': origin has thread_id=%s but delivery target lost it (deliver=%s, target=%s)rz   rá  r%  z*Job '%s': delivering to %s:%s thread_id=%s)re   ra   rk   Nr©   r0   rº   ÚDri   zunknown platform 'r˜  Ú
is_runningc                  ó   — y)NFr  r  rK   rB   ú<lambda>z*_prepare_target_delivery.<locals>.<lambda>,  s   � rK   r2   zOJob '%s': cron_continuable_surface=in_channel not supported on %s, using threadr‡   FrI   rX   rU  r>   r>  rV  rW  rš   rX  rE   rY  rZ  r[  r‹   r\  r]  r^  r_  r`  r  )r¬   r¥   r8   rJ   rr   rs   rŠ   rZ   rg   r9   r:   rN  rl   r®   r¯   r  r~  r7   rC   rƒ  r    rS  )rI   rd   r{  rš   rW  rX  Úmirror_enabledr‹   rš  r¥   rX   rG   rW   rE   rY   rY  r\  rZ  Úorigin_chat_typer[  r^  rF   ÚresolvedÚresolve_errrU  r>   r>  rV  r`  r]  r_  s                                  rB   Ú_prepare_target_deliveryré  ñ  s¡  € õ (Ø˜:Ñ&€MØ�YÑ€GØ—
‘
˜;Ó'€Iä˜SÓ!Ò' R€FØ—J‘J˜{Ó+€MÙ™YÜ�‰ØcØ�‰I�} c§g¡g¨i¸Ó&AÀ6õ	Kñ 
Ü�‰Ø8Ø�‰I�} g¨yô	:ô
 +¨6°=À'È9ÓU€MØ'ò OÔ,CØˆV >Àô-OÐñ /<�V—Z‘Z 	Ô*À€Nô ˜6Ÿ:™: kÓ2Ò8°bÓ9×?Ñ?ÓAÐØ# tÑ+ò ?ØÐÒ=¤ W£×!8Ñ!8¸Ó!=ð ð *ò dØÒbÔ6¸\ÐSaÔbð ðÙ˜M×/Ñ/Ó1Ó2ˆô
 6ØˆX�} f¨h¸ó@Ñ€HˆkàÐÜ˜3 ¨_Ô=ØØ;CÑ8€Iˆw˜¨ð
 	˜tÐ#ò 	9Ø˜Ðò	9à6ŒG�D˜,©Ó6Ó8ð ô 4°G¸]ÓKÈ|Ñ[ÐáØÐ'Ü,¨_¸mÔLä�‰Ø]Ø�G‰G�D˜#Ó ô	/ð #ÐÙÑ3Ñ8Jð ˆ	ð
 '+ÐáÙ"ØÐ'ØÐÙä8Ø� '¨4ó1ò 9Ø48ð 	áØ(ˆIÜò RÙðRÙ"ðRÙ2?ðRÙIPðRáðRá'0ðRá:AðRáSbðRñ (ðRñ 17ðRñ >BðRñ TcðRñ ð	Rñ &3ð	Rñ DRð	Rñ
 "ðRñ
 0;ðRñ
 PbðRñ .ðRñ F[ðRñ *ðRñ ?QðRð Røôk œÐ!ò Ü˜3Ð"4°]°OÀ1Ð EÀÔWÙðús   Ä/I É I.É-I.c           
     óô   — t        t        | |¬«      «      }|dk(  ry|dk(  r7t        j                  d| j	                  d| j	                  dd«      «      «       yd	|› �}t        j                  d
| d   |«       |S )uÓ   ``_deliver_result`` outcome when no target resolved: None (not a failure) for ``local`` and
    origin-less ``origin`` (CLI jobs never capture an origin â€” a spurious error every run), else
    an error string.rñ  r%  NrE   uk   Job '%s': deliver=origin but no origin or home channels â€” skipping delivery (output saved in last_output)ry   rz   r‡   z(no delivery target resolved for deliver=rƒ  )râ  rô  rr   r‰   r8   rs   )rI   r]  r-  r…  s       rB   Ú_unresolved_delivery_outcomerë  [  s~   € ô -Ô-AÀ#ÐS^Ô-_Ó`€MØ˜ÒØØ˜Ò Ü�‰ð>à�G‰G�F˜CŸG™G D¨#Ó.Ó/ô	1ð Ø4°]°OÐ
D€CÜ
‡N�N�> 3 t¡9¨cÔ2Ø€JrK   c               ó(  — | j                  dd«       | j                  dd«       t        | |¬«      }|st        | g «       t        | |«      S t        j
                  j                  dd«      }|r›|€™|t        | j                  d«      xs d«      k(  rxt        d„ |D «       «      rfd	d
l	m
} t        | g «        ||| ||¬«      }d	dl	m}	  |	|«      }
|
r|
d   dk(  rd| d<   d	dlm}  || d   «      xs i }|j                  d«      | d<   |S d	dlm} d}d}t!        j"                  t$        «      5  t'        j(                  «       }|j                  di «      j                  dd«      }ddd«       t+        |«      }g }|r5| j                  d| d   «      }d|› d| j                  dd«      › d|› d|› d�	}n|}d	dlm} d	dlm}  ||«       |j5                  |«      \  }}t7        |d«      }t9        |«      }|j;                  |«      }|t9        |«      z
  }|d	kD  r|› d�gng }	 t=        | |«      }|j5                  |«      \  }}t7        |xs dj?                  «       d «      }	  |«       }g }!d	}"|D �]  }#d	d#l"m#}$ |r|#d$   tH        k7  r |$|#d$   |«      s|"d%z  }"Œ*|#d$   tH        k(  rŒtK        | ||#d&   |¬«      }%|"| j                  dd«      z  }"|%rbd'|#d&   xs d(› �}&| j                  di «      j                  |&«      }'|'r|'d   d)vr|!jM                  |%«       |'r|'d   d*k(  r|jM                  |%«       ŒÂtO        | |#|||||||!¬+«	      }(|(€ŒÙg })|(jP                  xr tS        |(|||)|!|¬,«      }*|*rŒýtU        |(|||)|!«       �Œ |"t9        |«      k(  rd| d<   n|!jW                  |«       t        | |«       |!rd-jY                  |!«      S dS # 1 sw Y   �Œ]xY w# t$        $ r d}Y �Œ°w xY w# t$        $ r+}d!|› �} t@        jC                  d"| d   | «       | cY d}~S d}~ww xY w).av  Deliver job output to the configured target(s). With ``adapters``/``loop`` (gateway
    running) the live adapter is tried first (E2EE rooms can't use the standalone HTTP path), then
    standalone fallback. ``for_failure=True`` routes failure-category notices through the job's
    ``failure_deliver`` override when present (NS-788). Returns None on success, else an error.ru  Nrv  rñ  Ú_HERMES_CRON_EXTERNAL_WORKERr0   ri  c              3  ó4   K  — | ]  }|d    t         k7  –— Œ y­w)rF   N)r  )rP  rd   s     rB   rR  z"_deliver_result.<locals>.<genexpr>ˆ  s   è ø€ ÒRÀ�F˜:Ñ&Ô*;Õ;ÑRùs   ‚r   )Úenqueue_and_wait)Ú
get_statusrr  rq  T)Úget_jobrz   rI  r  rN   Úwrap_responsery   zCronjob Response: z

(job_id: z)
-------------

zI

To stop or manage this job, send me a new message (e.g. "stop reminder z").)r  )Úapply_media_policy_envzdelivery contentz£ media attachment(s) dropped by media path policy (missing file, denied prefix, or strict-mode miss); see gateway.strict / media_delivery_allow_dirs in config.yamlFzmirror payloadzfailed to load gateway config: rƒ  rf  rF   r]   rG   rs  rd  r{  Ú	ambiguous)r{  rš   rW  rX  rå  r‹   rš  r³  z; )-Úpoprø  rQ  rë  rì   r·  r8   r9   r¸  Úcron.delivery_queuerï  rð  rM  rñ  r¬   rã   r4   r5   r6   rQ   rR   rF  r  r  Úgateway.media_policyró  Úextract_mediarw   ræ  r  rU   r=   rr   r~  r¡  rg  r  rÝ  rË   ré  r`  r¼  rß  rÝ  rÌ   )+rI   rÁ  r{  rš   r]  r  Úexternal_executionrï  r~  rð  Údelivery_statusrñ  Ú	refreshedrã   rò  Úuser_cfgrX  rN  Ú	task_nameÚdelivery_contentr  ró  r   Úcleaned_delivery_contentÚrequested_mediaÚ_policy_droppedÚpolicy_drop_errorsrå  r  r‹   rW  rv   r…  rš  Úsuppressed_targetsrd   rg  Úbot_chat_errorÚreceipt_targetrÈ  r‰  r™  r3  s+                                              rB   Ú_deliver_resultr  r  sÂ  € ð ‡G�GÐ)¨4Ô0Ø‡G�GÐ2°DÔ9Ü'¨¸ÔE€GÙÜ% c¨2Ô.Ü+¨C°Ó=Ð=ô Ÿ™Ÿ™Ð(FÈÓKÐÙ˜xÐ/Ø"¤c¨#¯'©'°.Ó*AÒ*GÀRÓ&HÒHÜÑRÈ'ÔRÔRÝ8ä% c¨2Ô.Ù Ð!3°S¸'È{Ô[ˆÝ2Ù$Ð%7Ó8ˆÙ˜¨xÑ8¸LÒHØ:>ˆCÐ6Ñ7Ý%Ù˜C ™IÓ&Ò,¨"ˆ	Ø&/§m¡mÐ4JÓ&KˆÐ"Ñ#Øˆå2ð €MØ€HÜ	×	Ñ	œYÓ	'ñ LÜ×%Ñ%Ó'ˆØ Ÿ™ V¨RÓ0×4Ñ4°_ÀdÓKˆ÷Lô 4°HÓ=€Oð  "ÐÙØ—G‘G˜F C¨¡IÓ.ˆ	à   ð ,ØŸ™  bÓ)Ð*ð + àˆið %à%. K¨tð5ñ 	ð #Ðå:õ <Ù˜8Ô$Ø,?×,MÑ,MÐN^Ó,_Ñ)€KÐ)ô
  4Ð4LÐN`ÓaÐÜ˜+Ó&€OØ%×AÑAÀ+ÓN€Kà%¬¨KÓ(8Ñ8€Oð
 
˜1Ò	ð Ð
ð Hð 	Hñð #%ð	 ðÜ6°s¸HÓEˆð
 )×6Ñ6°wÓ?�N€A€{ô '¨Ò(9°r×'@Ñ'@Ó'BÐDTÓU€KðÙ$Ó&ˆð €OØÐØó #Zˆõ 	PÙ˜F :Ñ.Ô2CÒCÙ5°f¸ZÑ6HÈ(ÔSØ !Ñ#ÐØà�*ÑÔ!2Ò2Ü1°#°wÀÀyÑ@QÐ_jÔkˆNØ #§'¡'Ð*PÐRWÓ"XÑXÐÙØ#,¨V°IÑ->Ò-IÀ'Ð,JÐ!K�ØŸ'™'Ð"?ÀÓD×HÑHÈÓX�Ù '¨(Ñ"3Ð;PÑ"PØ#×*Ñ*¨>Ô:Ù˜w xÑ0°KÒ?Ø&×-Ñ-¨nÔ=Øä$Ø� (°¸fØ+Ø)°{ÐTcôeˆð ˆ9ØØ ˆØ×(Ñ(ò 
Ô-FØÐ'¨Ø'¸Ø1ô.
ˆ	ò
 ÜØÐ+¨[¸-ÈöZðE#ZðN œS ›\Ò)Ø6:ˆÐ2Ò3à×ÑÐ1Ô2Ü! #Ð'9Ô:Ù)8ˆ4�9‰9�_Ó%ÐB¸dÐB÷[Lñ Lûô\ ò Ø‹ðûô ò Ø/°¨sÐ3ˆÜ�‰�^ S¨¡Y°Ô4Ø�
ûðús<   Ä,7N>ÈO ÉO Î>OÏOÏOÏ	PÏ& PÐPÐP)Ú	scheduler)Úscheduler_preflight)Úscheduler_script)r?   r9   rï   r9   )rI   r<   rï   úOptional[dict]rb  )rI   r<   rS   r
  rï   rP   )
rE   r<   rX   r9   rG   r9   rW   rT  rï   rP   )
rI   r<   rd   r<   re   rP   ra   zOptional[bool]rï   rP   )rj   rP   rk   rT  rï   rP   )rt   r9   ru   r9   rï   r9   )rI   r<   rï   r9   )rI   r<   rt   r9   rï   r9   )NN)rI   r<   rX   r9   rG   r9   r‹   r9   rW   rT  rk   rT  r€   rP   rï   r“  )rI   r<   rG   r9   rï   rT  )rI   r<   rX   r9   rG   r9   rt   r9   rW   rT  r©   r9   rk   rT  r¡   rT  r¨   rT  rª   rT  r¢   rP   rï   rP   )NFN)rI   r<   rX   r9   rG   r9   rW   r9   r‹   r9   r¨   rT  rj   rP   rª   rT  rï   r“  )rI   r<   rX   r9   rG   r9   r‹   r9   rj   rP   rk   rT  r¨   rT  rª   rT  rï   rP   )rX   r9   rï   r9   )rX   r9   rï   rP   )rX   r9   )r0   )rò   r9   ró   r9   r=   rP   rï   r9   )rX   r9   rï   rT  )r  r  rï   r  )rï   z
list[dict])rE   r<   rï   rP   )rE   r<   )rX   r9   rG   r9   rf   rT  rï   r<   )rI   r<   r-  r9   r#  rP   rï   r
  )rï   r7  )
rF  rß  rB  r<   rC  r9   r•   Úfloatrï   zsubprocess.CompletedProcessrh  )rI   r<   rÁ  r9   rÂ  r9   r\  r
  r]  rP   rï   rT  )rç  r9   rï   rT  )rI   r<   rì  r9   rï   r
  )rç  r9   rï   z	List[str])rI   r<   r]  rP   )rI   r<   r]  rP   rï   z
List[dict])
rG   r9   r   rß  r  zdict | NonerI   r<   rï   rß  )rÎ   r9   )r‡   N)r‡  r9   r7  zOptional[list]rï   rP   )
r>  r   rG   r   rš   r   r‡  r9   rï   rP   )rS   r
  rï   rP   )rI   r<   rN  rß  rï   r“  )rI   r<   r…  r9   r"  rß  rï   r“  )rI   r<   r…  r9   rc  rP   rï   r“  )rI   r<   rX   r9   rd   r<   )r‰  rS  rï   z tuple[Optional[str], dict, dict])r‰  rS  r˜  r9   r‹  rT  rŒ  r<   r™  rß  rš  rß  rN  rß  rï   ztuple[bool, bool, Any])
r‰  rS  r�  r<   r   rß  rš  rß  rï   r“  )r‰  rS  rï   r“  )r‰  rS  r¹  r9   r   rß  r™  rß  rš  rß  rN  rß  rï   rP   )r‰  rS  rÁ  r9   r   rß  rï   ztuple[Any, Optional[str]])r‰  rS  rÁ  r9   r   rß  r™  rß  rš  rß  rï   r“  )rI   r<   rd   r<   rX  rP   rå  rP   r‹   r9   rš  rß  rï   zOptional[_TargetDelivery])rI   r<   r]  rP   rï   rT  )rI   r<   rÁ  r9   r]  rP   rï   rT  )jrk  Ú
__future__r   rÁ  Úconcurrent.futuresrÐ  r4   rÔ  Úloggingrì   r²  r¿  r°  ry  r   Útypingr   r   r   Ú	getLoggerrr   Ú	frozensetrÜ   rH   rà   rñ   rC   rJ   rU   rZ   rö  rg   rl   rw   r|   r~   r�   r¼   r    r¸   r½   r¿   rÐ   rÚ   rÞ   rá   rç   rõ   r÷   rù   rþ   r  r	  r  r  r  r!  r3  r9  r>  rT  rV  rO  rG  r[  rÝ  râ  rï  r  r£  r)  r*  rð  rô  rø  rú  r  r  r.  r1  r9  r@  rF  rQ  rS  r  rq  r~  rƒ  rŽ  r£  r«  r±  r¼  rÚ  rß  ré  rë  r  rN   r  rQ   r  rw  r	  r  r  rK   rB   ú<module>r     s7  ðñõ #ã Û Û Û Û Û 	Û Û Û 
Ý !ß &Ñ &ð 
ˆ×	Ñ	Ð+Ó	,€ñ &ò 'ó Ð ñ '¨ ~Ó6Ð ð5ØÐ ð5àÐ'ð5ð Ð%ð5ð Ð!ð	5ð
 Ð#ð5ð Ð+ð5ð 
Ðð5ð Ð!ð5ð Ð'ð5ð Ð#ð5ð Ð!ð5ð Ð#ð5ð Ð-ð5ð Ð!ð5ð Ð'ð5ð  Ð3ð!5Ð ð& !5Ð6GÐHÐ óó(ô(ð&OØ&3ðOØ8<óOð" &'¸1ÀaÐUVÑWÐ ð UYñØ	ðØðØ/3ðØCQðØ]aóó6"ó/ó(VóAð
 _cØ!ð'
à6;ñ'
Ø	ð'
Ø!ð'
Ø,/ð'
Ø>Að'
ØN[ð'
àð'
à/3ð'
ð 
ó'
ð\ %,°wÈGÑTÐ óð2 HLØV[ñ'Ø	ð'Ø'*ð'Ø58ð'Ø@Cð'ØS`ð'àð'à*ð'à7Dð'ð ð'ð )6ð'ð PTð'ð 
ó	'ðX UYð!FØ	ð!FØ'*ð!FØ58ð!FØEHð!FØWZð!Fàð!Fà,0ð!FàDQð!Fð 
ó!FðL 8<ÐW[ñØ	ðØ'*ðØ58ðØGJðØVZðàðà'4ðàGTðð 
óóB4ó"	óQóIó
ðÀeõ ó*8óJóò6	!óó"óJLó#ôð >CñPVØ	ðPVØ!ðPVØ6:ðPVàóPVófóð$ Ð àÐ Ø>Ð óAó$]ð8 _cØ-2ñY$Ø&*ðY$Ø7DóY$óx	ñ ˜U˜GÓ$€ð Ð à Ð ó
óó0Uð <Aõ 'ð AFõ  óF+ñ ÒIÓJ€ÙÒBÓC€ð `dð:Øð:Ø(,ð:Ø8Cð:ØPTð:à	ó:ôz.ð BFð$Øð$Ø0>ð$ØJNó$óN#óLóað* ÷ 6ð  6ó ð 6óFóSð6HØ	ð6HØ(+ð6HØ59ó6HórSó-;ð`K-ØðK-Ø&)ðK-Ø<IðK-Ø[_ðK-àðK-à*.ðK-àDHðK-ð óK-ð\<Øð<Ø(,ð<Ø;?ð<ØRVð<Ø[_ó<ó*.Uðb>Øð>Ø&)ð>Ø8<ð>ØPTð>àð>à/3ð>ð 
ó>ðB@Øð@Ø!$ð@Ø37ð@Ø<Uó@ðF&Øð&Ø!$ð&Ø37ð&ØHLð&Ø_cð&à	ó&ðDgRØ	ðgRØðgRØIMðgRØ_cðgRàðgRà'+ðgRð ógRóTð0 26ðVCØNSñVCØ	ðVCØðVCØGKðVCàóVCõv %Ý 2Þ ,rK   