+
    iHàj:  ã                  óª  a € 0 t $ R t^ RIHt ^ RIt^ RIt^ RIt^ RIt^ RIt^ RI	t	^ RI
t
^ RIt^ RIt^ RIt^ RIHtHt ^ RIHtHtHtHtHtHt ^ RIHt ^ RIHt ^ RIHtH t H!t!H"t"H#t#H$t$ ]PJ                  ! ]&4      t'^
t(^<t)^t*Rt+R	t,]-! 4       t.R
]/R&   ]P`                  ! 4       t1]	Pd                  ! ],R7      t3R]/R&   ]P`                  ! 4       t4Rs5R]/R&   ] ! R R] 4      4       t6R R lt7R R lt8R-R R llt9R R lt:R R lt;R R lt<R R  lt=R! R" lt>R# R$ lt?R% R& lt@R' R( ltA ! R) R*]P„                  4      tC]Pˆ                  ! ]C4      tER+ R, ltFR# ).ab  Outbound webhooks: ``hooks.outbound`` entries (url, events, secret_env|secret, matcher for
pre/post_tool_call, timeout clamped to [1, 60], name) -> notify-only callbacks on the plugin hook
manager, so every ``invoke_hook()`` site can POST lifecycle events (mirror of
``gateway/platforms/webhook.py``).  Fire-and-forget through a bounded queue + one daemon worker,
so a target can never block a tool call or influence agent flow.  HMAC-SHA256 signed
(``X-Hermes-Signature-256: sha256=<hex>`` over the raw body) when a secret is configured;
``HERMES_SAFE_MODE=1`` skips registration; registration is idempotent.
)ÚannotationsN)Ú	dataclassÚfield)ÚAnyÚDictÚListÚOptionalÚSetÚTuple)Úerror)Úrequest)Ú_TOOL_EVENTSÚ_ToolMatcherMixinÚ_forget_home_registrationsÚ	_home_keyÚ_payload_fieldsÚ_utc_now_isog      ð?é   zset[tuple[str, str, str]]Ú_registered)Úmaxsizez%queue.Queue[Optional[dict[str, Any]]]Ú_delivery_queuezOptional[threading.Thread]Ú_workerc                  ó    € ] tR t^6t$ RtRtR]R&   R]R&   RtR]R&   R	tR
]R&   R	t	R
]R&   ]
tR]R&   ]! R	RR7      tR]R&   ]R R l4       tRtR	# )ÚWebhookTargetzDParsed and validated representation of one ``hooks.outbound`` entry.zoutbound webhookÚstrÚurlz	list[str]ÚeventsÚ ÚnameNzOptional[str]ÚsecretÚmatcherÚintÚtimeoutF)ÚdefaultÚreprzOptional[re.Pattern]Úcompiled_matcherc               ó   € V ^8„  d   QhRR/# )é   Úreturnr   © )Úformats   "Ú</home/ubuntu/.hermes/hermes-agent/agent/outbound_webhooks.pyÚ__annotate__ÚWebhookTarget.__annotate__C   s   € ÷ %ñ %�sñ %ó    c                	óB   € V P                   ;'       g    V P                  # ©N)r   r   )Úselfs   &r+   ÚlabelÚWebhookTarget.labelB   s   € à�y‰y×$Ð$˜DŸH™HÐ$r.   r)   )Ú__name__Ú
__module__Ú__qualname__Ú__firstlineno__Ú__doc__Ú_MATCHER_KINDÚ__annotations__r   r   r    ÚDEFAULT_TIMEOUT_SECONDSr"   r   r%   Úpropertyr2   Ú__static_attributes__r)   r.   r+   r   r   6   sa   ‡ áNØ&€MØ	ƒHØÓØ€Dˆ#ƒNØ €FˆMÓ Ø!€Gˆ]Ó!Ø*€GˆSÓ*Ù-2¸4ÀeÔ-LÐÐ*ÓLàô%ó ô%r.   r   c               ó    € V ^8„  d   QhRRRR/# ©r'   ÚcfgzOptional[dict[str, Any]]r(   zlist[WebhookTarget]r)   )r*   s   "r+   r,   r,   G   s   € ÷ $ñ $Ð6ð $Ð;Nñ $r.   c                ó  € ^ RI Hp V! 4       '       d   . # \        V \        4      '       g   . # ^ RIHp V! R4      '       d   \        P                  R4       . # \        V 4      pV'       g   . # ^ RI	H
p V! 4       p\        4       p. p\        ;_uu_ 4        V FÏ  pRp	VP                   FŸ  p
WjVP                  3pV\        9   d   K  VP                   P#                  V
. 4      P%                  \'        W¨4      4       \        P)                  V4       Rp	\        P                  RW¨P*                  VP,                  VP.                  4       K¡  	  V	'       g   K¾  VP%                  V4       KÑ  	  R	R	R	4       V#   + '       g   i     T# ; i)
u½   Register every configured outbound webhook on the plugin manager.  Malformed ``hooks.outbound``
means zero targets â€” never raises.  Returns the targets that ended up wired (deduplicated).©Úsafe_worker_enabled)Úenv_var_enabledÚHERMES_SAFE_MODEu<   HERMES_SAFE_MODE=1 â€” outbound webhook registration skipped)Úget_plugin_managerFTz?outbound webhook registered: %s -> %s (matcher=%s, timeout=%ds)N)Úagent.safe_worker_policyrC   Ú
isinstanceÚdictÚutilsrD   ÚloggerÚinfoÚiter_configured_targetsÚhermes_cli.pluginsrF   r   Ú_registered_lockr   r   r   Ú_hooksÚ
setdefaultÚappendÚ_make_callbackÚaddr2   r    r"   )r@   rC   rD   ÚtargetsrF   ÚmanagerÚhome_keyÚ
registeredÚtargetÚ	wired_anyÚeventÚkeys   &           r+   Úregister_from_configr]   G   s7  € õ =á×ÒØˆ	Ü�cœ4× Ò Øˆ	Ý%ÙÐ)×*Ò*Ü�‰ÐRÔSØˆ	Ü% cÓ*€GßØˆ	Ý5Ù Ó"€GÜ‹{€HØ&(€Jß	Ö	ÛˆFØˆIØŸœ�Ø¨¯
©
Ð3�Øœ+Ô%ÙØ—‘×)Ñ)¨%°Ó4×;Ñ;¼NÈ5Ó<YÔZÜ—‘ Ô$Ø �	Ü—‘ØUØŸ<™<¨¯©¸¿¹öñ '÷ ‰yØ×!Ñ! &Ö)ñ ÷ 
ð  Ð÷! 
Ö	ð  Ðús   ÂB<E5ÅE5Å5F	c               ó    € V ^8„  d   QhRRRR/# r?   r)   )r*   s   "r+   r,   r,   n   s    € ÷ iñ iÐ!9ð iÐ>Qñ ir.   c                óŒ  € \        V \        4      '       g   . # V P                  R4      p\        V\        4      '       d   VP                  R4      MRpVf   . # \        V\        4      '       g,   \        P                  R\        V4      P                  4       . # R \        V4       4        Uu. uF
  q3f   K  VNK  	  up# u upi )zNParse ``hooks.outbound`` without registering anything (``hermes hooks list``).ÚhooksÚoutboundNz8hooks.outbound must be a list of webhook targets; got %sc              3  ó<   "  € T F  w  r\        W4      x € K  	  R # 5ir0   )Ú_parse_single_target)Ú.0ÚiÚentrys   &  r+   Ú	<genexpr>Ú*iter_configured_targets.<locals>.<genexpr>y   s   é € ÐVÁ~¹8¸1Ô,¨Q×6Ð6Ã~ùs   ‚)	rH   rI   ÚgetÚlistrK   ÚwarningÚtyper4   Ú	enumerate)r@   Ú	hooks_cfgÚrawÚts   &   r+   rM   rM   n   sœ   € ä�cœ4× Ò Øˆ	Ø—‘˜Ó €IÜ'1°)¼T×'BÒ'Bˆ)�-‰-˜
Ô
#È€CØ
‚{Øˆ	Ü�cœ4× Ò Ü�‰ÐQÔSWÐX[ÓS\×SeÑSeÔfØˆ	ÙVÄyÐQTÄ~ÔVÓhÑV�!�AˆAÑVÑhÐhùÒhs   Â.CÂ8Cc               ó    € V ^8„  d   QhRRRR/# )r'   r"   Úfloatr(   Úboolr)   )r*   s   "r+   r,   r,   |   s   € ÷ 	5ñ 	5�5ð 	5 4ñ 	5r.   c                óÜ  € \         P                  ! 4       V ,           p\         P                  ! 4       V8  d[   \        P                  ;_uu_ 4        \        P                  ^ 8X  d    RRR4       R#  RRR4       \         P
                  ! R4       Kt  \        P                  ;_uu_ 4        \        P                  ^ 8H  uuRRR4       #   + '       g   i     L^; i  + '       g   i     R# ; i)zSBlock until all queued deliveries are done (or *timeout* elapses); True if drained.NTg{®Gáz”?)ÚtimeÚ	monotonicr   Úall_tasks_doneÚunfinished_tasksÚsleep)r"   Údeadlines   & r+   Úflushr{   |   s”   € ä�~Š~Ó 'Õ)€HÜ
�.Š.Ó
˜XÔ
%Ü×+×+Ó+Ü×/Ñ/°1Ô4Ø÷ ,Ñ+Ø4÷ ,ô 	�
Š
�4ÖÜ	×	'×	'Ó	'Ü×/Ñ/°1Ñ4÷ 
(Ò	'÷	 ,×+ú÷ 
(×	'Ð	'ús   ÁCÂ)CÃC	ÃC+	c               ó   € V ^8„  d   QhRR/# ©r'   r(   ÚNoner)   )r*   s   "r+   r,   r,   ˆ   s   € ÷ (ñ ( $ñ (r.   c                 óZ   € ^ RI Hp  \        \        \        4       \        V ! 4       4       R# )a  Re-register outbound webhooks after a plugin force-reload cleared ``_hooks``.  Only the
current home's idempotence keys are cleared so a force-reload in one profile cannot
invalidate another profile's still-live registration.

Mirrors ``agent.shell_hooks.re_register_config_hooks``: config-owned outbound-webhook callbacks live in
the same ``_hooks`` dict that ``PluginManager.discover_and_load(force=True)`` clears via ``unload()``,
so without this the force-reloaded profile's outbound webhooks go silently inert (#92682 review).
©Úload_configN)Úhermes_cli.configr�   r   r   rO   r]   r€   s    r+   Úre_register_config_hooksrƒ   ˆ   s   € õ .Üœ{Ô,<Ô=Ü™›Ö'r.   c               ó   € V ^8„  d   QhRR/# r}   r)   )r*   s   "r+   r,   r,   –   s   € ÷ 	ñ 	˜ñ 	r.   c                 ó  € \         ;_uu_ 4        \        P                  4        RRR4         \        P	                  4        \        P                  4        K+    + '       g   i     L<; i  \        P                   d     R# i ; i)zAClear the idempotence set and drain the queue.  Test-only helper.N)rO   r   Úclearr   Ú
get_nowaitÚ	task_doneÚqueueÚEmptyr)   r.   r+   Úreset_for_testsr‹   –   sY   € ç	Ö	Ü×ÑÔ÷ 
ðØÜ×&Ñ&Ô(Ü×%Ñ%Ö'÷ 
×	ûô �;‰;ô Úðús   �A­+A+ ÁA(	Á+BÂBc               ó$   € V ^8„  d   QhRRRRRR/# )r'   Úindexr!   ro   r   r(   zOptional[WebhookTarget]r)   )r*   s   "r+   r,   r,   ¢   s"   € ÷ =ñ = ð =¨#ð =Ð2Iñ =r.   c                óê  a € ^ RI Hp R V 3R llp\        V\        4      '       g   V! R\	        V4      P
                  4       R# VP                  R4      p\        V\        4      '       d   VP                  4       '       g   V! R4       R# VP                  4       pVP                  4       P                  R4      '       g   V! R	V4       R# VP                  4       P                  R4      '       d	   V! R
4       VP                  R4      pRP                  \        V4      4      p\        V\        4      '       d	   V'       g   V! RV4       R# V Uu. uF  qwV9   g   K  VNK  	  ppV F  pWr9  g   K  V! RWv4       K  	  V'       g   V! R4       R# VP                  R4      p	V	e!   \        V	\        4      '       g   V! R4       Rp	V	eF   \        ;QJ d    R V 4       F  '       g   K   RM	  RM! R V 4       4      '       g   V! RV	4       Rp	VP                  R\        4      p
 \!        V
4      pVP                  R4      pVP                  R4      p\        V\        4      '       dZ   VP                  4       '       dD   ^ RIHp V! VP                  4       R4      ;'       g    RpVf   V! RVP                  4       4       M3VP                  R4      p\        V\        4      '       d   V'       d   TMRp\+        YH\        V\        4      '       d   VP                  4       MRVV	\-        ^\/        V\0        4      4      R7      # u upi   \"        \$        3 d    T! RT
\        4       \        p EL?i ; i) é    )ÚVALID_HOOKSc               ó$   € V ^8„  d   QhRRRRRR/# )r'   Úmsgr   Úargsr   r(   r~   r)   )r*   s   "r+   r,   Ú*_parse_single_target.<locals>.__annotate__¥   s&   € ÷ Añ A�#ð A˜cð A dñ Ar.   c                óH   <€ \         P                  ! R V ,           S.VO5!   R# )zhooks.outbound[%d]N)rK   rk   )r’   r“   r�   s   &*€r+   ÚwarnÚ"_parse_single_target.<locals>.warn¥   s   ø€ Ü�ŠÐ+¨cÕ1°5Ð@¸4Ö@r.   z7 must be a mapping with 'url' and 'events' keys; got %sNr   z is missing a non-empty 'url'úhttp://u(   .url must be http(s); got %r â€” skippedu^   .url uses plain http:// â€” payloads (including tool inputs) travel unencrypted. Prefer https.r   z, z, needs a non-empty 'events' list (valid: %s)z&: unknown event %r ignored (valid: %s)u     has no valid events â€” skippedr    z).matcher must be a string regex; ignoringc              3  ó2   "  € T F  q\         9   x € K  	  R # 5ir0   )Ú_TOOL_SCOPED_EVENTS)rd   Úes   & r+   rg   Ú'_parse_single_target.<locals>.<genexpr>Å   s   é € Ð&PÉÀAÔ,?Ö'?Ëùs   ‚TFu[   .matcher=%r will be ignored â€” matcher is only honored for pre_tool_call / post_tool_call.r"   z3.timeout must be an int (got %r); using default %dsr   Ú
secret_env)Ú
get_secretr   uL   .secret_env=%r is not set in the environment â€” deliveries will be UNSIGNEDr   )r   r   r   r   r    r"   )r˜   zhttps://)rN   r�   rH   rI   rl   r4   ri   r   ÚstripÚlowerÚ
startswithÚjoinÚsortedrj   Úanyr;   r!   Ú	TypeErrorÚ
ValueErrorÚagent.secret_scoperž   r   ÚmaxÚminÚMAX_TIMEOUT_SECONDS)r�   ro   r�   r–   r   Ú
events_rawÚ
valid_listÚevr   r    Útimeout_rawr"   r   r�   rž   r   s   f&              r+   rc   rc   ¢   sÊ  ø€ Ý.÷Að Aô �cœ4× Ò ÙÐFÌÈSË	×HZÑHZÔ[ÙØ
�'‰'�%‹.€CÜ�cœ3×Ò s§y¡y§{¢{ÙÐ,Ô-ÙØ
�)‰)‹+€CØ�9‰9‹;×!Ñ!Ð"9×:Ò:ÙÐ7¸Ô=ÙØ
‡y�yƒ{×Ñ˜i×(Ò(ÙÐmÔnØ—‘˜Ó"€JØ—‘œ6 +Ó.Ó/€JÜ�j¤$×'Ò'¯zÙÐ;¸ZÔHÙÙ&0ÓF¡j ¸+Ñ4EŸ˜¡j€FÐFÛˆØÖ ÙÐ9¸2ÖJñ ÷ ÙÐ/Ô0ÙØ�g‰g�iÓ €GØÒ¤:¨g´s×#;Ò#;ÙÐ8Ô9ØˆØÒ§3£3Ñ&PÉÓ&P§3§3¢3Ñ&PÉÓ&P×#PÒ#PÙÐjÐlsÔtØˆØ—'‘'˜)Ô%<Ó=€Kð*Ü�kÓ"ˆð �7‰7�6‹?€Dð
 —‘˜Ó&€JÜ�*œc×"Ò" z×'7Ñ'7×'9Ò'9Ý1Ù˜J×,Ñ,Ó.°Ó3×;Ð;°tˆØŠ>ÙÐ_Ðak×aqÑaqÓasÔtøà—‘˜Ó"ˆÜ% f¬c×2Ò2·v‘À4ˆÜØ´ZÀÄc×5JÒ5J T§Z¡Z¤\ÐPRÐ[aØ¤ Q¬¨GÔ5HÓ(IÓ!Jôð ùòE Gøô" ”zÐ"ô *ÙÐBÀKÔQhÔiÜ)‹ð*ús   ÅMÅMÈ'M	 Í	%M2Í1M2c               ó    € V ^8„  d   QhRRRR/# )r'   r[   r   rY   r   r)   )r*   s   "r+   r,   r,   â   s   € ÷ ñ ˜#ð  }ñ r.   c                óp   a a€ R V V3R llpRS  RSP                    R2Vn        VP                  Vn        V# )zABuild the notify-only closure ``invoke_hook()`` calls per firing.c               ó    € V ^8„  d   QhRRRR/# )r'   Úkwargsr   r(   r~   r)   )r*   s   "r+   r,   Ú$_make_callback.<locals>.__annotate__å   s   € ÷ Dñ D˜Cð D Dñ Dr.   c                 ó†  <€ ^ RI Hp V! 4       '       d   R# S\        9   d)   SP                  V P	                  R4      4      '       g   R# \
        P                  ! 4       P                  p \        SW4      p\        \        SSY24      4       R#   \         d(    \        P                  RSSP                  RR7        R# i ; i)r�   rB   NÚ	tool_namezBoutbound webhook payload serialization failed (event=%s target=%s)T©Úexc_info)rG   rC   rš   Úmatches_toolri   ÚuuidÚuuid4ÚhexÚ_serialize_payloadÚ	ExceptionrK   rk   r2   Ú_enqueueÚ_build_delivery)r²   rC   Údelivery_idÚbodyr[   rY   s   ,   €€r+   Ú	_callbackÚ!_make_callback.<locals>._callbackå   s¥   ø€ Ý@á× Ò ÙØÔ'Ô'°×0CÑ0CÀFÇJÁJÈ{ÓD[×0\Ò0\ÙÜ—j’j“l×&Ñ&ˆð	Ü% e¨VÓAˆDô 	” ¨°ÓBÖCøô ô 	Ü�N‰NÐ_ÐafÐhn×htÑhtð  @DˆNô  EÚð	ús   Á*B Â.C Â?C zoutbound_webhook[Ú:Ú])r2   r4   r6   )r[   rY   rÂ   s   ff r+   rS   rS   â   s@   ù€ ÷Dñ Dð -¨U¨G°1°V·\±\°NÀ!ÐD€IÔØ&×/Ñ/€IÔØÐr.   c               ó(   € V ^8„  d   QhRRRRRRRR/# )r'   r[   r   r²   údict[str, Any]rÀ   r(   Úbytesr)   )r*   s   "r+   r,   r,   ù   s/   € ÷ Pñ P˜cð P¨>ð PÈð PÐPUñ Pr.   c                ó®   € ^ RI Hp RV RV! 4       /\        V4      CRVR\        4       /Cp\        P
                  ! VR\        R7      P                  R4      # )	z×Render the POST body: shell-hooks stdin shape plus delivery metadata.  ``delivery_id``
(also the ``X-Hermes-Delivery`` header) and ``timestamp`` live inside the HMAC-signed
body, so they double as replay protection.)Úget_active_profile_nameÚhook_event_nameÚprofilerÀ   Ú	timestampF)Úensure_asciir#   úutf-8)Úhermes_cli.profilesrÊ   r   r   ÚjsonÚdumpsr   Úencode)r[   r²   rÀ   rÊ   Úpayloads   &&&  r+   r¼   r¼   ù   sY   € õ <à˜5 )Ñ-DÓ-FðÜJYÐZ`ÓJaðà�{ K´³ñ€Gô �:Š:�g¨E¼3Ô?×FÑFÀwÓOÐOr.   c          
     ó,   € V ^8„  d   QhRRRRRRRRRR	/# )
r'   r[   r   rY   r   rÁ   rÈ   rÀ   r(   rÇ   r)   )r*   s   "r+   r,   r,     s8   € ÷ Cñ C˜3ð C¨ð C¸Uð CÐQTð CÐYgñ Cr.   c                ó<  € R RRRRV RV/pVP                   '       dV   \        P                  ! VP                   P                  R4      V\        P
                  4      P                  4       pRV 2VR&   R	VP                  R
VP                  RV RVRVRVP                  /# )zContent-Typezapplication/jsonz
User-AgentzHermes-Agent-Outbound-WebhookzX-Hermes-EventzX-Hermes-DeliveryrÏ   zsha256=zX-Hermes-Signature-256r   r2   r[   rÁ   Úheadersr"   )
r   ÚhmacÚnewrÓ   ÚhashlibÚsha256Ú	hexdigestr   r2   r"   )r[   rY   rÁ   rÀ   r×   Údigests   &&&&  r+   r¿   r¿     s¨   € àÐ*¨LÐ:YØ˜%Ð!4°kð€Gð ‡}‡}€}Ü—’˜&Ÿ-™-×.Ñ.¨wÓ7¸¼w¿~¹~ÓN×XÑXÓZˆØ.5°f°XÐ,>ˆÐ(Ñ)Ø�6—:‘:˜w¨¯©°g¸uÀfÈdÐT]Ð_fÐhqÐsy÷  tBñ  tBð  Cð  Cr.   c               ó    € V ^8„  d   QhRRRR/# ©r'   ÚdeliveryrÇ   r(   r~   r)   )r*   s   "r+   r,   r,     s   € ÷ 
ñ 
�~ð 
¨$ñ 
r.   c                ó4  € \         e   \         P                  4       '       g‡   \        ;_uu_ 4        \         e   \         P                  4       '       gN   \        P                  ! \
        RRR7      s \         P                  4        \        P                  ! \        RR7       R R R 4        \        P                  V 4       R #   + '       g   i     L(; i  \        P                   d/    \        P                  R\         T R,          T R,          4        R # i ; i)	Nzoutbound-webhooksT)rY   r   Údaemonç      @©r"   uE   outbound webhook queue full (%d pending) â€” dropping %s event for %sr[   r2   )r   Úis_aliveÚ_worker_lockÚ	threadingÚThreadÚ_worker_loopÚstartÚatexitÚregisterr{   r   Ú
put_nowaitr‰   ÚFullrK   rk   ÚQUEUE_MAX_SIZE)rà   s   &r+   r¾   r¾     s°   € ä‚œg×.Ñ.×0Ò0ßŽ\ÜŠ¤g×&6Ñ&6×&8Ò&8Ü#×*Ò*´,ÐEXÐaeÔf�Ü—‘”ô —’¤¨sÕ3÷ ð
Ü×"Ñ" 8Ö,÷ �\ûô �:‰:ô 
Ü�‰ØSÜ˜H WÕ-¨x¸Õ/@÷	
ð
ús$   ±"CÁACÂ*C ÃC	Ã?DÄDc               ó   € V ^8„  d   QhRR/# r}   r)   )r*   s   "r+   r,   r,   %  s   € ÷ 
(ñ 
(�dñ 
(r.   c                 óN  €  \         P                  4       p  V e   \        V 4       \         P                  4        K;    \         dE    \	        T \
        4      '       d   T P                  R4      MRp\        P                  RTR R7        Ldi ; i  \         P                  4        i ; i)Tr2   Ú?z-outbound webhook delivery crashed (target=%s)r¶   )	r   ri   Ú_deliverr½   rH   rI   rK   rk   rˆ   )rà   r2   s     r+   ré   ré   %  s†   € Ø
Ü"×&Ñ&Ó(ˆð	(ØÒ#Ü˜Ô"ô
 ×%Ñ%Ö'øô	 ô 	bÜ-7¸Ä$×-GÒ-G�H—L‘L Ô)ÈSˆEÜ�N‰NÐJÈEÐ\`ˆNÖað	bûô ×%Ñ%Õ'ús"   —< ¼ABÂB Â
BÂB ÂB$c                  ó    € ] tR tRtRtR tRtR# )Ú_NoRedirectHandleri2  z˜Refuse redirects: urllib would turn a redirected POST into a body-less GET,
silently dropping the signed payload. Any 3xx surfaces as HTTPError instead.c                	ó   € R # r0   r)   )r1   ÚreqÚfpÚcoder’   r×   Únewurls   &&&&&&&r+   Úredirect_requestÚ#_NoRedirectHandler.redirect_request6  s   € Ùr.   r)   N)r4   r5   r6   r7   r8   rû   r=   r)   r.   r+   rõ   rõ   2  s   † ñTör.   rõ   c               ó    € V ^8„  d   QhRRRR/# rß   r)   )r*   s   "r+   r,   r,   =  s   € ÷ ñ �~ð ¨$ñ r.   c                óZ  € V R,          V R,          r!Rp\        ^\        ^,           4       FÍ  p\        P                  ! V R,          V R,          V R,          RR7      p \        P                  WPR	,          R
7      ;_uu_ 4       p\        VR^È4      pRRR4       ^ÈXu;8:  d   R8  d   M M\        P                  RWV4        R# RV 2pV\        8  g   K¬  \&        P(                  ! \*        V,          4       KÏ  	  \        P                  R\        WV4       R#   + '       g   i     L‘; i  \        P                   d­   pRTP                   2pRTP                  u;8:  d   R8  d<   M M8\        P                  RYY8P                  P                  RR4      4        Rp? R# RTP                  u;8:  d   R8  d&   M  Rp?Lû\        P                  RYT4        Rp? R#  Rp?ELRp?i\         d4   p\!        T4      ;'       g    \#        T4      P$                  p Rp?EL[Rp?ii ; i)zUPOST with bounded retries: retry on connection errors and 5xx; 4xx and 3xx are final.r[   r2   r   r   rÁ   r×   ÚPOST)Údatar×   Úmethodr"   rä   ÚstatusNi,  z.outbound webhook delivered: %s -> %s (HTTP %d)zHTTP i�  u{   outbound webhook target redirected (event=%s target=%s): %s -> %s â€” redirects are not followed; update the configured urlÚLocationrò   iô  uC   outbound webhook rejected (event=%s target=%s): %s â€” not retryingzMoutbound webhook delivery failed after %d attempt(s) (event=%s target=%s): %s)ÚrangeÚMAX_DELIVERY_ATTEMPTSÚ
urlrequestÚRequestÚ_openerÚopenÚgetattrrK   ÚdebugÚurlerrorÚ	HTTPErrorrù   rk   r×   ri   r½   r   rl   r4   ru   ry   ÚRETRY_BACKOFF_SECONDS)	rà   r[   r2   Ú
last_errorÚattemptr÷   Úrespr  Úexcs	   &        r+   ró   ró   =  s±  € à˜GÕ$ h¨wÕ&7ˆ5Ø€JÜ˜Ô1°AÕ5Ö6ˆÜ× Ò  ¨%¥°xÀÕ7GÐQYÐZcÕQdÐmsÔtˆð	8Ü—‘˜c°IÕ+>�×?Ô?À4Ü   x°Ó5�÷ @à�fÖ"˜s×"Ü—‘ÐMÈuÐ]cÔdÚØ   Ð)ˆJð Ô*Ö*Ü�JŠJÔ,¨wÕ6Ö7ñ/ 7ô0 ‡N�NØWÜ˜u¨Zö÷+ @×?ûô ×!Ñ!ô 
	Ø  §¡ 
Ð+ˆJØ�c—h‘hÖ$ ×$Ü—‘ð:Ø;@È×U`ÑU`×UdÑUdÐeoÐqtÓUuôö Ø�c—h‘hÖ$ ×$Ó$Ü—‘ÐdÐfkÐt~ÔÞõ %ûô ô 	8Ü˜S›×7Ð7¤T¨#£Y×%7Ñ%7ŽJûð	8úsU   Á%D-ÂDÂ1D-ÃD-ÄD*Ä%D-Ä-H*ÅAG)Æ%G)ÇG)Ç)H*Ç6H*Ç7(H%È%H*)rã   )GÚ__conditional_annotations__r8   Ú
__future__r   rë   rÚ   rØ   rÑ   Úloggingr‰   Úrerç   ru   r¹   Údataclassesr   r   Útypingr   r   r   r   r	   r
   Úurllibr   r  r   r  Úagent.shell_hooksr   rš   r   r   r   r   r   Ú	getLoggerr4   rK   r;   rª   r  r  rï   Úsetr   r:   ÚLockrO   ÚQueuer   ræ   r   r   r]   rM   r{   rƒ   r‹   rc   rS   r¼   r¿   r¾   ré   ÚHTTPRedirectHandlerrõ   Úbuild_openerr  ró   )r  s   @r+   Ú<module>r!     s?  øðôõ #ã Û Û Û Û Û Û 	Û Û Û ß (ß 8× 8Ý $Ý (÷÷ ð 
×	Ò	˜8Ó	$€àÐ ØÐ ØÐ ØÐ Ø€ñ *-«€Ð&Ó .Ø—>’>Ó#Ð à9>¿ºÈ^Ô9\€Ð6Ó \Ø�~Š~Ó€Ø&*€Ð	#Ó *ð ô%Ð%ó %ó ð%õ $õNi÷	5õ(õ	õ=õ@õ.PõCõ
õ&
(ô˜×7Ñ7ô ð ×
!Ò
!Ð"4Ó
5€÷r.   