+
    jHàjZ‹  ã                  ó  € 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Ht ]P                  ! R4      t]P"                  ! R4      tRtR@tR R ltR	 R
 ltR tR R ltR R ltR R ltR R ltR R ltR R ltR R ltR R ltR R lt R R lt!R  R! 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(RAR. R/ llt)R0RR1RR2RR3]/R4 R5 llt*R6 R7 lt+R8 R9 lt,R3]/R: R; llt-R< R= lt.RBR> R? llt/R# )CaÌ  Relay/connector support package for the Hermes gateway.

EXPERIMENTAL gateway side of the "Gateway Gateway" relay design: a generic
``RelayAdapter`` plus the wire-serializable ``CapabilityDescriptor`` the connector
hands it at handshake, and the production ``WebSocketRelayTransport``. The public
API MAY CHANGE without a deprecation cycle until >=2 real Class-1 platforms have
shaken out the schema (``website/docs/developer-guide/relay-connector-contract.md``). Activation is
config-driven: the relay platform is registered when a connector relay URL is set
(``GATEWAY_RELAY_URL`` env or ``gateway.relay_url``), like ``gateway.proxy_url``,
unless the effective relay platform configuration explicitly disables it.
)ÚannotationsN)ÚOptionalzgateway.relayz9[A-Za-z0-9_-]+(?:\.[A-Za-z0-9_-]+){2,}|[A-Za-z0-9_-]{32,}g      .@c               ó   € V ^8„  d   QhRR/# ©é   ÚreturnÚdict© )Úformats   "Ú;/home/ubuntu/.hermes/hermes-agent/gateway/relay/__init__.pyÚ__annotate__r   .   s   € ÷ 0ñ 0�4ñ 0ó    c                 óx   €  ^ RI Hp  V ! 4       p\        T\        4      '       d   T# / #   \         d    / u # i ; i)uR   The full gateway config, or ``{}`` â€” config absence/parse must never crash boot.)Ú_load_gateway_config)Úgateway.runr   Ú	ExceptionÚ
isinstancer   )r   Úcfgs     r   Ú	_load_cfgr   .   sA   € ðÝ4á"Ó$ˆô ˜S¤$×'Ò'ˆ3Ð/¨RÐ/øô ô ØŠ	ðús   ‚) ©9¸9c               ó   € V ^8„  d   QhRR/# r   r	   )r
   s   "r   r   r   9   s   € ÷ 4ñ 4�dñ 4r   c                 óh   € \        4       P                  R4      p \        V \        4      '       d   V # / # )z1The ``gateway:`` block of config.yaml, or ``{}``.Úgateway)r   Úgetr   r   )Úblocks    r   Ú_gateway_cfgr   9   s)   € ä‹K�O‰O˜IÓ&€EÜ˜u¤d×+Ò+ˆ5Ð3°Ð3r   c                 ó„   € ^ RI Hp  V ! 4       '       g   \        P                  ! 4       # ^ RIHp ^ RIHp V! V! 4       4      # )a  The launch profile's runtime scope once the gateway multiplexes, ``nullcontext`` before.

Self-provision runs at startup, before any turn binds a profile, and under multiplexing the
Nous Portal and inference routing overrides only resolve inside a profile scope. The scope is
built from the profile's files like a turn's (``gateway.run._profile_runtime_scope``), not via
``launch_profile_scope_if_multiplexed``, whose first entry freezes the launch env snapshot
before startup has written ``GATEWAY_RELAY_*`` into ``os.environ``.
)Úis_multiplex_active)Ú_profile_runtime_scope)Úget_process_hermes_home)Úagent.secret_scoper   Ú
contextlibÚnullcontextr   r   Úhermes_constantsr   )r   r   r   s      r   Ú_launch_profile_scoper#   ?   s4   € õ 7á× Ò Ü×%Ò%Ó'Ð'Ý2Ý8á!Ñ"9Ó";Ó<Ð<r   c               ó$   € V ^8„  d   QhRRRRRR/# )r   Úenv_varÚstrÚcfg_keyr   r	   )r
   s   "r   r   r   R   s&   € ÷ Gñ G˜ð G sð G¨sñ Gr   c                óè   € \         P                  P                  V R4      P                  4       pT;'       g<    \	        \        4       P                  VR4      ;'       g    R4      P                  4       # )zZEnv var first (Docker/NAS stamp), then ``gateway.<cfg_key>``; stripped, ``""`` when unset.Ú )ÚosÚenvironr   Ústripr&   r   )r%   r'   Úvalues   && r   Ú_env_or_cfgr.   R   sR   € ä�J‰J�N‰N˜7 BÓ'×-Ñ-Ó/€EØ×FÐF”Cœ›×*Ñ*¨7°BÓ7×=Ð=¸2Ó>×DÑDÓFÐFr   c               ó$   € V ^8„  d   QhRRRRRR/# )r   r%   r&   r'   r   úOptional[str]r	   )r
   s   "r   r   r   X   s!   € ÷ =ñ =˜Sð =¨3ð =°=ñ =r   c                óJ   € \        W4      P                  R4      ;'       g    R# )zP``_env_or_cfg`` for URL-shaped values: trailing slash stripped, None when unset.Ú/N)r.   Úrstrip)r%   r'   s   &&r   Ú_env_or_cfg_urlr4   X   s    € ä�wÓ(×/Ñ/°Ó4×<Ð<¸Ð<r   c               ó   € V ^8„  d   QhRR/# ©r   r   Úboolr	   )r
   s   "r   r   r   ]   s   € ÷ 7ñ 7 4ñ 7r   c                 óL  € ^ RI Hp Hp ^ RIHpHpHp ^ RIHp  V! V! 4       4      p\        T\        4      '       g   R# \        TP                  R4      \        4      '       d   TP                  R4      M/ pT! Yg/ 4      pT! YgP                  R4      / Y€P                  .4       TP                  R4      p	\        T	\        4      '       d(   T	P                  R/ 4      P                  R	4      '       g   R# TP                  T	4      P                  '       * #   \         d     R# i ; i)
u%  ``platforms.relay.enabled: false`` in the profile's YAML (user or managed).

Same files, merge and boolean normalization as the gateway loader (a malformed user
file drops the whole YAML layer there too), minus its env/plugin side effects, so a
standalone scheduler can ask without bootstrapping the gateway.
Mirrors the loader's ``_enabled_explicit`` rule: only a YAML ``enabled`` key is
authoritative â€” a legacy ``gateway.json`` block is advisory for relay exactly as it
is for every other platform, and an absent key keeps URL-only activation.
)ÚPlatformÚPlatformConfig)Úbridge_platform_shared_keysÚmerge_platform_sectionsÚread_yaml_layers)Úget_hermes_homeFr   Ú	platformsÚrelayÚextraÚ_enabled_explicit)Úgateway.configr9   r:   Úgateway.config_loaderr;   r<   r=   r"   r>   r   r   r   r   ÚRELAYÚ	from_dictÚenabled)
r9   r:   r;   r<   r=   r>   r   r   r?   r   s
             r   Úrelay_explicitly_disabledrH   ]   sé   € ÷ 8ßlÑlÝ0ðÙ™Ó0Ó1ˆô �cœ4× Ò ÙÜ$.¨s¯w©w°yÓ/AÄ4×$HÒ$Hˆc�g‰g�iÔ Èb€GÙ'¨°bÓ9€IÙ §[¡[°Ó%=¸rÀ9Ï~É~ÐN^Ô_Ø�M‰M˜'Ó"€EÜ�eœT×"Ò"¨%¯)©)°G¸RÓ*@×*DÑ*DÐEX×*YÒ*YÙØ×'Ñ'¨Ó.×6Ñ6Ô6Ð6øô ô Úðús   šD ÄD#Ä"D#c               ó   € V ^8„  d   QhRR/# ©r   r   r0   r	   )r
   s   "r   r   r   z   s   € ÷ =ñ =�=ñ =r   c                 ó>   € \        4       '       d   R# \        RR4      # )zMEffective connector URL; an explicit platform disable vetoes even an env URL.NÚGATEWAY_RELAY_URLÚ	relay_url)rH   r4   r	   r   r   rM   rM   z   s   € ä ×"Ò"ÙÜÐ.°Ó<Ð<r   c               ó   € V ^8„  d   QhRR/# )r   r   zlist[tuple[str, str]]r	   )r
   s   "r   r   r   �   s   € ÷ ñ Ð#8ñ r   c                 óò  € \         P                  P                  RR4      P                  R4       U u. uF*  q P	                  4       '       g   K  V P	                  4       NK,  	  pp V'       g   R.# \        4       p. pV Fq  pVP                  V4      ;'       g    / p\        V\        4      '       d*   \        VP                  RR4      4      P	                  4       MRpVP                  WF34       Ks  	  V# u up i )aŽ  The ordered (platform, bot_id) pairs this gateway fronts on one WS connection,
from ``GATEWAY_RELAY_PLATFORMS`` (comma-sep) and ``GATEWAY_RELAY_BOT_IDS`` (JSON
``{"discord": {"botId": "..."}}``). The FIRST pair is the handshake/descriptor
default; a platform absent from the ids map gets an empty bot_id (the connector
rejects it with a structured failure). ``[("relay", "")]`` when nothing is set.ÚGATEWAY_RELAY_PLATFORMSr)   Ú,ÚbotId)r@   r)   )
r*   r+   r   Úsplitr,   Ú_relay_bot_ids_mapr   r   r&   Úappend)Úpr?   ÚidsÚoutÚplatformÚentryÚbot_ids          r   Úrelay_platform_identitiesr\   �   sÈ   € ô %'§J¡J§N¡NÐ3LÈbÓ$Q×$WÑ$WÐX[Ô$\ÓjÑ$\˜q×`gÑ`g×`i”�—‘–Ñ$\€IÐjßØˆÐÜ
Ó
€CØ!#€CÛˆØ—‘˜Ó!×'Ð' RˆÜ8BÀ5Ì$×8OÒ8O”�U—Y‘Y˜w¨Ó+Ó,×2Ñ2Ô4ÐUWˆØ�
‰
�HÐ%Ö&ñ ð €Jùò ks   ²C4ÁC4c               ó   € V ^8„  d   QhRR/# )r   r   zset[str]r	   )r
   s   "r   r   r   “   s   € ÷ Gñ G ñ Gr   c                 ó�   € \        4       '       d   \        4       # \        4        U Uu0 uF  w  rV R8w  g   K  V kK  	  upp # u upp i )u/  Logical platform names the relay fronts, minus the generic ``relay`` fallback.
Same env source the live adapter's identity set comes from, so config-time
validation (cron delivery preflight) and fire-time routing can never disagree â€”
and it needs no live adapter, so a standalone scheduler can use it.r@   )rH   Úsetr\   )rV   Ú_s     r   Úrelay_fronted_platformsra   “   s;   € ô
 !×"Ò"Ü‹uˆÜ3Ô5ÔFÑ5‘$�!¸¸g¹�AˆAÑ5ÒFÐFùÓFs
   ¨A¸Ac               ó   € V ^8„  d   QhRR/# r   r	   )r
   s   "r   r   r   �   s   € ÷ 
ñ 
˜Dñ 
r   c                 ó$  € \         P                  P                  RR4      P                  4       p V '       g   / #  \        P
                  ! V 4      p\        V\        4      '       d   V# / #   \         d    \        P                  R4       / u # i ; i)zYParse ``GATEWAY_RELAY_BOT_IDS``; a malformed map yields ``{}`` rather than crashing boot.ÚGATEWAY_RELAY_BOT_IDSr)   z:GATEWAY_RELAY_BOT_IDS is not valid JSON; treating as empty)r*   r+   r   r,   ÚjsonÚloadsr   r   r   ÚloggerÚwarning)ÚrawÚparseds     r   rT   rT   �   sr   € ä
�*‰*�.‰.Ð0°"Ó
5×
;Ñ
;Ó
=€CßØˆ	ðÜ—’˜C“ˆÜ# F¬D×1Ò1ˆvÐ9°rÐ9øÜô Ü�‰ÐSÔTØŠ	ðús   º-A* Á(A* Á*"BÂBc               ó   € V ^8„  d   QhRR/# )r   r   ztuple[str, str]r	   )r
   s   "r   r   r   ª   s   € ÷ *ñ * ñ *r   c                 ó$   € \        4       ^ ,          # )uL   The PRIMARY (platform, bot_id) â€” first of ``relay_platform_identities()``.)r\   r	   r   r   Úrelay_platform_identityrm   ª   s   € ä$Ó& qÕ)Ð)r   c               ó   € V ^8„  d   QhRR/# )r   r   z#tuple[Optional[str], Optional[str]]r	   )r
   s   "r   r   r   ¯   s   € ÷ 0ñ 0ÐBñ 0r   c                 ób   € \        RR4      p \        RR4      pT ;'       g    RT;'       g    R3# )zäThe (gateway_id, upgrade_secret) from enrollment (``GATEWAY_RELAY_ID`` /
``GATEWAY_RELAY_SECRET``, then ``gateway.relay_id`` / ``gateway.relay_secret``).
Either absent -> ``(None, None)`` and the transport dials unauthenticated.ÚGATEWAY_RELAY_IDÚrelay_idÚGATEWAY_RELAY_SECRETÚrelay_secretN©r.   )Ú
gateway_idÚsecrets     r   Úrelay_connection_authrw   ¯   s7   € ô Ð/°Ó<€JÜÐ/°Ó@€FØ×Ð˜$ § ¨$Ð/Ð/r   c               ó   € V ^8„  d   QhRR/# rJ   r	   )r
   s   "r   r   r   ¸   ó   € ÷ Gñ G˜ñ Gr   c                 ó   € \        RR4      # )a>  The gateway's own PUBLIC inbound URL, asserted to the connector at provision
(``GATEWAY_RELAY_ENDPOINT`` / ``gateway.relay_endpoint``). Stored on the tenant's
route rows; gateway-asserted but tenant-scoped, so a dishonest gateway can only
misdirect its OWN inbound. Absent -> outbound-only (no inbound routes written).ÚGATEWAY_RELAY_ENDPOINTÚrelay_endpoint©r4   r	   r   r   r|   r|   ¸   ó   € ô
 Ð3Ð5EÓFÐFr   c               ó   € V ^8„  d   QhRR/# )r   r   ú	list[str]r	   )r
   s   "r   r   r   À   s   € ÷ <ñ <˜)ñ <r   c                 óT  € \         P                  P                  RR4      P                  4       p V '       g¤   \	        4       P                  RR4      p\        V\        \        34      '       dK   V Uu. uF=  p\        V4      P                  4       '       g   K$  \        V4      P                  4       NK?  	  up# \        T;'       g    R4      P                  4       p V P                  R4       Uu. uF*  q"P                  4       '       g   K  VP                  4       NK,  	  up# u upi u upi )a8  Discriminators (scope_ids / chat_ids / paths) this gateway's tenant owns. The
connector writes one route row per (routeKey -> tenant, endpoint), so keys only
take effect alongside ``relay_endpoint()``. ``GATEWAY_RELAY_ROUTE_KEYS`` is
comma-separated; ``gateway.relay_route_keys`` may be a list or a comma string.ÚGATEWAY_RELAY_ROUTE_KEYSr)   Úrelay_route_keysrQ   )
r*   r+   r   r,   r   r   ÚlistÚtupler&   rS   )ri   ÚvalÚks      r   rƒ   rƒ   À   sÄ   € ô
 �*‰*�.‰.Ð3°RÓ
8×
>Ñ
>Ó
@€CßÜ‹n× Ñ Ð!3°RÓ8ˆÜ�cœD¤%˜=×)Ò)Ù,/ÓB©C q´3°q³6·<±<·>”N”C˜“F—L‘L–N©CÑBÐBÜ�#—)�)˜‹n×"Ñ"Ó$ˆØ"Ÿy™y¨œ~Ó;™~˜!·±·ŒIˆA�G‰GŽI™~Ñ;Ð;ùò Cùâ;s   Á1!D ÂD Ã-D%Ä	D%c               ó   € V ^8„  d   QhRR/# rJ   r	   )r
   s   "r   r   r   Î   s   € ÷ Qñ Q˜=ñ Qr   c                 ó.   € \        RR4      ;'       g    R# )a<  Stable per-instance id forwarded at provision (``GATEWAY_RELAY_INSTANCE_ID`` /
``gateway.relay_instance_id``): binds the connector's ``gatewayId -> instanceId``
so inbound routes per-instance rather than tenant-broadcast (NAS stamps its
``AgentInstance.id``). Tenant-scoped like ``relay_endpoint()``; absent -> null.ÚGATEWAY_RELAY_INSTANCE_IDÚrelay_instance_idNrt   r	   r   r   r‹   r‹   Î   s   € ô
 Ð2Ð4GÓH×PÐPÈDÐPr   c               ó   € V ^8„  d   QhRR/# rJ   r	   )r
   s   "r   r   r   Ö   ry   r   c                 ó   € \        RR4      # )a0  The gateway's WAKE URL forwarded at provision (``GATEWAY_RELAY_WAKE_URL`` /
``gateway.relay_wake_url``): a payload-free poke the connector GETs when a
going-idle destination receives its first buffered event, so a suspended gateway
wakes, reconnects and drains. Absent -> no wake (buffering still works).ÚGATEWAY_RELAY_WAKE_URLÚrelay_wake_urlr}   r	   r   r   r�   r�   Ö   r~   r   c               ó   € V ^8„  d   QhRR/# rJ   r	   )r
   s   "r   r   r   Þ   s   € ÷ ñ ˜Mñ r   c                 óJ  € \         P                  P                  RR4      P                  4       p V '       gI    ^ RIHp \        V! 4       P                  RR4      ;'       g    R4      P                  4       p V R8X  d   Rp V R,          ;'       g    R#   \         d    Rp  L+i ; i)u3  The human-facing agent display name forwarded at provision â€” the connector's
multi-agent reply-attribution prefix (``**<displayName>:** ``).
``GATEWAY_RELAY_DISPLAY_NAME`` env, then the skin's branded agent name (a skin
rename propagates on the next boot). Absent -> connector's linked-owner fallback.

The PRIMARY source for the connector's multi-agent reply-attribution prefix (gateway-gateway #171): in a
multi-agent scope the shared bot prepends ``**<displayName>:** `` to this instance's replies.
Gateway-asserted but safely scoped exactly like ``relay_instance_id()`` / ``relay_wake_url()`` â€” the
tenant stays token-verified, so a dishonest gateway can only label its OWN instance. Absent -> the
connector stores null and attribution falls back to the instance's linked-owner identity, else skips the
prefix.
ÚGATEWAY_RELAY_DISPLAY_NAMEr)   )Úget_active_skinÚ
agent_namezHermes Agent:Né@   NN)	r*   r+   r   r,   Úhermes_cli.skin_enginer“   r&   Úget_brandingr   )r-   r“   s     r   Úrelay_display_namer˜   Þ   s�   € ô �J‰J�N‰NÐ7¸Ó<×BÑBÓD€Eßð	Ý>ä™Ó)×6Ñ6°|ÀRÓH×NÐNÈBÓO×UÑUÓWˆEð �NÔ"ØˆEà��:×Ð˜Ðøô ô 	ØŠEð	ús   ¸(B Á!B ÂB"Â!B"c               ó$   € V ^8„  d   QhRRRRRR/# )r   Úrelay_dial_urlr&   Úpathr   r	   )r
   s   "r   r   r      s!   € ÷ 5ñ 5 3ð 5¨cð 5°cñ 5r   c                ó&   € ^ RI Hp V! V 4       V 2# )uJ   ``ws(s)://â€¦/relay`` dial URL -> ``http(s)://â€¦{path}`` connector route.)Úmedia_base_url)Úgateway.relay.mediar�   )rš   r›   r�   s   && r   Ú_connector_urlrŸ      s   € å2á˜^Ó,Ð-¨d¨VÐ4Ð4r   c               ó    € V ^8„  d   QhRRRR/# )r   rš   r&   r   r	   )r
   s   "r   r   r     s   € ÷ >ñ > 3ð >¨3ñ >r   c                ó   € \        V R 4      # )z/relay/provision)rŸ   )rš   s   &r   Ú_provision_urlr¢     s   € Ü˜.Ð*<Ó=Ð=r   c               ó(   € V ^8„  d   QhRRRRRRRR/# )r   Úurlr&   ÚtokenÚbodyr   ÚtimeoutÚfloatr	   )r
   s   "r   r   r     s(   € ÷ 8ñ 8�Cð 8 ð 8¨4ð 8¸%ñ 8r   c                óà   € \         P                  P                  V \        P                  ! V4      P                  R4      RRRV 2RRRR/R7      p\         P                  P                  WCR	7      # )
zLBearer-authenticated JSON POST; returns the open response (caller reads it).úutf-8ÚPOSTÚAuthorizationzBearer úContent-Typeúapplication/jsonÚAccept©ÚdataÚmethodÚheaders©r§   )ÚurllibÚrequestÚRequestre   ÚdumpsÚencodeÚurlopen)r¤   r¥   r¦   r§   Úreqs   &&&& r   Ú
_json_postr¼     so   € ä
�.‰.×
 Ñ
 ØÜ�ZŠZ˜Ó×$Ñ$ WÓ-Øà˜w u gÐ.ØÐ.ØÐ(ð
ð	 !ó 	€Cô �>‰>×!Ñ! #Ð!Ó7Ð7r   c               ó    € V ^8„  d   QhRRRR/# )r   rY   r0   r   zOptional[dict]r	   )r
   s   "r   r   r     s   € ÷ ;ñ ; ]ð ;¸nñ ;r   c                óF  a a
€ S f   \        4       w  o pS '       d   S R8X  d   R# Rp. p \        4       o
V
V 3R lp\        R V! 4        4       / 4      pRV9   d   VP                  R4      pM$S
P                  R4      e   S
P                  R4      pVP                  R4      pVf   S
P                  R4      p\	        V\
        \        34      '       dK   V Uu. uF=  p\        V4      P                  4       '       g   K$  \        V4      P                  4       NK?  	  ppMq\	        V\        4      '       d\   VP                  4       '       dF   VP                  R4       Uu. uF*  qwP                  4       '       g   K  VP                  4       NK,  	  pp\        P                  P                  S P                  4        R2R	4      P                  4       P                  4       pVR9   p	Vf   V'       g   V	'       g   R# R
S R\        V4      RVRV	/# u upi u upi   \         d     L’i ; i)aq  Project a fronted platform's RELEVANCE config into the connector's generic vocabulary.

The connector's relevance gate reasons over a platform-agnostic policy keyed by
``(tenant, platform, instanceId)``: ``requireAddress`` <- ``require_mention``,
``freeResponseScopes`` <- ``free_response_channels``, ``allowOtherBots`` <-
``{PLATFORM}_ALLOW_BOTS`` in {"mentions","all"}. Read from the platform's config
block (``discord:``), falling back to the bridged top-level keys, then env.
``platform`` defaults to the PRIMARY fronted platform. Returns None when relay
isn't configured or nothing is CONFIGURED to declare, so the connector's default
(mention-gated) applies. The condition is "require_mention is unset", NOT "falsy":
an EXPLICIT ``require_mention: false`` is a non-default choice that MUST be
declared or the connector would mention-gate an agent configured to free-respond.
Nr@   c               3  óL  <"  € SP                  S4      x € SP                  R 4      ;'       g    / P                  R4      ;'       g    / p \        V \        4      '       d   V P                  S4      MRx € SP                  R4      ;'       g    / P                  S4      x € R# 5i)r   r?   N)r   r   r   )Úgw_platformsr   rY   s    €€r   Ú_candidatesÚ+relay_relevance_policy.<locals>._candidates3  s€   øé € Ø—'‘'˜(Ó#Ò#ØŸG™G IÓ.×4Ð4°"×9Ñ9¸+ÓF×LÐLÈ"ˆLÜ0:¸<Ì×0NÒ0N�,×"Ñ" 8Ô,ÐTXÒXØ—7‘7˜;Ó'×-Ð-¨2×2Ñ2°8Ó<Ô<ùs   ƒAB$ÁAB$ÂB$c              3  óV   "  € T F  p\        V\        4      '       g   K  Vx € K!  	  R # 5i©N)r   r   )Ú.0Úcs   & r   Ú	<genexpr>Ú)relay_relevance_policy.<locals>.<genexpr>9  s   é € ÐI¡M˜q´ZÀÄ4×5HŸš£Mùs   ‚)Ÿ
)Úrequire_mentionÚfree_response_channelsrQ   Ú_ALLOW_BOTSr)   rY   ÚrequireAddressÚfreeResponseScopesÚallowOtherBots>   ÚallÚmentions)rm   r   Únextr   r   r„   r…   r&   r,   rS   r   r*   r+   ÚupperÚlowerr7   )rY   Ú_bot_idrÉ   Úfree_responserÁ   Úplat_cfgÚfrcrÆ   Úallow_bots_envÚallow_other_botsr   s   f         @r   Úrelay_relevance_policyrÚ     s¿  ù€ ð ÒÜ3Ó5Ñˆ�'ß�x 7Ô*Ùà€OØ!€MðÜ‹kˆö	=ô ÑI¡K¤MÓIÈ2ÓNˆà Ô(Ø&Ÿl™lÐ+<Ó=‰OØ�W‰WÐ&Ó'Ò3Ø!Ÿg™gÐ&7Ó8ˆOà�l‰lÐ3Ó4ˆØŠ;Ø—'‘'Ð2Ó3ˆCÜ�cœD¤%˜=×)Ò)Ù58ÓK±S°¼CÀ»F¿L¹L¿Nœ^œS ›VŸ\™\ž^±SˆMÐKˆMÜ˜œS×!Ò! c§i¡i§k¢kØ03·	±	¸#´ÓL±¨1Ç'Á'Ç)œY˜QŸW™WžY±ˆMÐLô
 —Z‘Z—^‘^ x§~¡~Ó'7Ð&8¸Ð$DÀbÓI×OÑOÓQ×WÑWÓY€NØ%Ð)<Ñ<ÐàÒ§}×=MÙà�HØœ$˜Ó/Ø˜mØÐ*ð	ð ùò LùâLøÜô ÙðúsH   ªB,H Ã!HÃ<HÄH Ä+H ÅH ÅHÅ7HÆH È
H ÈH ÈH Úinstance_idÚwake_urlÚdisplay_namer§   c               óH   € V ^8„  d   QhRRRRRRRRRRRRR	R
RRRRRRRRRR/# )r   Úprovision_urlr&   Úaccess_tokenru   rY   r[   Úgateway_endpointr0   Ú
route_keysr€   rÛ   rÜ   rÝ   r§   r¨   r   r   r	   )r
   s   "r   r   r   X  s�   € ÷ Hñ HàðHð ðHð ð	Hð
 ðHð ðHð $ðHð ðHð ðHð ðHð  ðHð ðHð 
ñHr   c           
     óâ  € RTRTRTRT;'       g    RRV/pRV3RV3R	V	33 F  w  rÍV'       g   K  WÛV&   K  	   \        WWº4      ;_uu_ 4       p\        P                  ! VP                  4       P	                  4       4      pR
R
R
4       \        X\        4      '       g   \        R4      hTP                  R4      '       g!   TP                  R4      RJd   \        R4      hT#   + '       g   i     Lj; i  \
        P                  P                   dŸ   pRp \        P                  ! TP                  4       P	                  4       4      ;'       g    / P                  RR4      pM  \         d     Mi ; i\        RTP                   2T'       d   RT 2,           4      ThR,           4      ThR
p?i\
        P                  P                   d   p\        RTP                   24      ThR
p?ii ; i)a-  POST ``/relay/provision``; return ``{secret, deliveryKey, tenant, gatewayId,
routeKeys}`` (the connector validates ``access_token`` against NAS, derives the
tenant, mints the per-gateway secret and upserts route rows). Raises RuntimeError
with a user-facing message on any non-2xx / transport failure.Ú	gatewayIdrY   rR   ÚgatewayEndpointr)   Ú	routeKeysÚ
instanceIdÚwakeUrlÚdisplayNameNÚerrorzconnector returned HTTP z: úcould not reach connector: z)connector returned an unexpected responserv   ÚsecretIssuedFz5connector returned an unexpected response (no secret))r¼   re   rf   ÚreadÚdecoderµ   rê   Ú	HTTPErrorr   r   ÚRuntimeErrorÚcodeÚURLErrorÚreasonr   r   )rß   rà   ru   rY   r[   rá   râ   rÛ   rÜ   rÝ   r§   r¦   Úkeyr-   ÚrespÚpayloadÚexcÚdetails   $$$$$$$$$$$       r   Ú_post_provisionrù   X  sÆ  € ð& 	�ZØ�HØ�ØÐ+×1Ð1¨rØ�Zð€Dð % kÐ2°YÀÐ4IÈMÐ[gÐKhÓi‰
ˆß‰5Ø�‹Iñ jðPÜ˜°T×CÔCÀtÜ—j’j §¡£×!3Ñ!3Ó!5Ó6ˆG÷ Dô �gœt×$Ò$ÜÐFÓGÐGð& �;‰;�x× Ò  W§[¡[°Ó%@ÈÓ%Mô ÐRÓSÐSØ€N÷S D×Cûä�<‰<×!Ñ!ô Øˆð	Ü—j’j §¡£×!2Ñ!2Ó!4Ó5×;Ð;¸×@Ñ@ÀÈ"ÓM‰FøÜô 	Ùð	úäØ& s§x¡x jÐ1Çf°r¸&¸°]ÕUó
àð	ØRTÕUó
àð	ûô �<‰<× Ñ ô PÜÐ8¸¿¹¸ÐEÓFÈCÐOûðPúsl   ºC6 Á3C#ÂC6 Ã#C3	Ã.C6 Ã3C6 Ã6G.ÄF.ÄAE%Å$F.Å%E3Å0F.Å2E3Å3;F.Æ. G.ÇG.ÇG)Ç)G.c               ó   € V ^8„  d   QhRR/# )r   r   r&   r	   )r
   s   "r   r   r   £  s   € ÷ X ñ X  sñ X r   c            	     ó4  a€ \          U u/ uFB  q \        P                  P                  RV P	                  4        2R4      P                  4       bKD  	  up oSR,          '       gˆ   \        4       P                  R4      p\        V\        4      '       d   TM/ p\          FJ  p SV ,          ;'       g4    \        VP                  V R4      ;'       g    R4      P                  4       SV &   KL  	  V3R l\          4       w  r#rEV'       g+   ^ RI
Hp \        4       ;_uu_ 4        V! 4       uuRRR4       # V'       Eg2   V'       Eg)   \        P                  P                  VRR	R
/R7      p\        P                  P!                  V\"        R7      ;_uu_ 4       pVP%                  4       P'                  4       P                  4       p	RRR4       Rp
X	P)                  R4      '       dX    \*        P,                  ! V	4      ;'       g    / P                  R4      p\        V\        4      '       d   VP                  4       p
M\0        P3                  V	4      '       d   T	p
V
'       g   \5        R4      hV
# V'       d	   V'       g   V'       d   RMRp\5        RV R24      hRRRVRV/pV'       d   W]R&   \        P                  P                  V\        P6                  P9                  V4      P;                  R4      RRRR	R/R7      p\        P                  P!                  V\"        R7      ;_uu_ 4       p\*        P,                  ! VP%                  4       P'                  4       4      pRRR4       X;'       g    / P                  R4      p\        V\        4      '       d   VP                  4       '       g   \5        R4      hVP                  4       # u up i   + '       g   i     EL¬; i  + '       g   i     EL(; i  \.         d    Rp ELòi ; i  + '       g   i     L³; i)a¤  Resolve the caller-identity bearer token the connector introspects to a tenant.

Canonical resolver shared by runtime self-provision and ``hermes gateway enroll``.
Modes, in precedence order:
  1.  Generic OIDC client-credentials (self-hosted IdP): ``gateway.idp.token_url``
      (``GATEWAY_RELAY_IDP_TOKEN_URL``) set together with client id + secret ->
      POST the OAuth2 ``client_credentials`` grant.
  1b. Ambient token endpoint: ``token_url`` with NEITHER client_id nor
      client_secret is a metadata-server-style endpoint (e.g. Domino's
      ``$DOMINO_API_PROXY/access-token``): a plain GET whose body IS the token,
      raw JWT or a JSON envelope with ``access_token``. Possession of the
      (typically loopback) endpoint is the credential.
  2.  Nous Portal (default): ``resolve_nous_access_token()``.

Raises on failure; callers decide whether that's fatal (enroll CLI) or a graceful
boot no-op (self-provision).
ÚGATEWAY_RELAY_IDP_r)   Ú	token_urlÚidpc              3  ó6   <"  € T F  pSV,          x € K  	  R # 5irÄ   r	   )rÅ   r‡   Úenvs   & €r   rÇ   Ú0_resolve_relay_identity_token.<locals>.<genexpr>½  s   øé € Ð1LÁ)¸Q°#°a·&²&Ã)ùs   ƒ)Úresolve_nous_access_tokenNÚGETr¯   zapplication/json, text/plain)r²   r³   r´   Ú{rà   zúno client_id/client_secret configured, so gateway.idp.token_url was treated as an ambient token endpoint (GET), but the response body was not a token. For the OAuth2 client_credentials grant, configure client_id and client_secret alongside token_url.Úclient_secretÚ	client_idzFgateway.idp.token_url is configured with a partial client credential (zº missing). Configure both client_id and client_secret for the OAuth2 client_credentials grant, or neither to treat token_url as an ambient token endpoint (plain GET returning the token).Ú
grant_typeÚclient_credentialsÚscoperª   r«   r­   z!application/x-www-form-urlencodedr®   r°   z3IdP client_credentials response had no access_token)Ú	_IDP_KEYSr*   r+   r   rÒ   r,   r   r   r   r&   Úhermes_cli.authr  r#   rµ   r¶   r·   rº   Ú_HTTP_TIMEOUT_Srí   rî   Ú
startswithre   rf   Ú
ValueErrorÚ_AMBIENT_TOKEN_SHAPEÚ	fullmatchrð   ÚparseÚ	urlencoder¹   )r‡   rþ   rý   r  r  r	  r  r»   rõ   r¦   r¥   Úenvelope_tokenÚmissingÚformrö   rà   r   s                   @r   Ú_resolve_relay_identity_tokenr  £  sH  ø€ õ$ U^Ó
^ÑT]ÈqŒb�j‰j�n‰nÐ1°!·'±'³)°Ð=¸rÓB×HÑHÓJÒJÑT]Ñ
^€CØˆ{×Ôô ‹n× Ñ  Ó'ˆÜ ¤T×*Ò*‰c°ˆßˆAØ˜•V×@Ð@œs 3§7¡7¨1¨b£>×#7Ð#7°RÓ8×>Ñ>Ó@ˆC�‹Fñ ä1LÅ)Ó1LÑ.€I˜-çÝ=ô #×$Õ$Ù,Ó.÷ %Ò$÷ ˆ9Ÿ]˜]ä�n‰n×$Ñ$Ø˜e¨hÐ8VÐ-Wð %ó 
ˆô �^‰^×#Ñ# C´Ð#×AÔAÀTØ—9‘9“;×%Ñ%Ó'×-Ñ-Ó/ˆD÷ BàˆØ�?‰?˜3×Òð&Ü"&§*¢*¨TÓ"2×"8Ð"8°b×!=Ñ!=¸nÓ!M�ô
 ˜.¬#×.Ò.Ø&×,Ñ,Ó.�øÜ!×+Ñ+¨D×1Ò1ØˆEßÜðCóð ð ˆçŸM÷ &/‘/°KˆÜðØˆyð LðMó
ð 	
ð Ð.°¸YÈÐYfÐg€DßØˆW‰Ü
�.‰.×
 Ñ
 ØœŸ™×.Ñ.¨tÓ4×;Ñ;¸GÓDÈVØÐ!DÀhÐPbÐcð !ó €Cô 
�‰×	Ñ	 ¬_Ð	×	=Ô	=ÀÜ—*’*˜TŸY™Y›[×/Ñ/Ó1Ó2ˆ÷ 
>à—M�M˜r×&Ñ& ~Ó6€LÜ�l¤C×(Ò(°×0BÑ0B×0DÒ0DÜÐPÓQÐQØ×ÑÓÐùòM _÷ %×$Ð$ú÷ B×AÐAûô ô &Ø!%“ð&ú÷H 
>×	=úsB   ŠAOÄOÆ-OÇ"O3 Ç?O3 Ì)3PÏO	ÏO0	Ï3PÐPÐP	c               ó   € V ^8„  d   QhRR/# r6   r	   )r
   s   "r   r   r   þ  s   € ÷ rñ r˜dñ rr   c                 ó2  € \        4       p V '       g   R# \        4       w  rV'       d    V'       d   \        P                  R4       R#  \	        4       p\        4       p \        P                  ! 4       P                  4       p\        P                  P                  RR4      P                  4       ;'       g    RT;'       g    R 2p\        4       p\        4       p	\!        4       p
\#        4       p\%        4       p. p/ pT EF  w  pp \'        \)        T 4      TYTTYšTTR	7
      pTP-                  T4       TP                  R4      '       g   KN  \        P                  P                  R4      '       d   Ku  \/        TP                  R4      ;'       g    T4      \        P                  R&   \/        TR,          4      \        P                  R&   \/        TP                  R4      ;'       g    R4      \        P                  R&   EK  	  T'       g/   \        P                  RRP1                  R T 4       4      4       R# \        P                  P                  R4      '       g)   \        P                  RRP1                  T4      T4       R# \        P                  R\        P                  P                  RT4      \/        TP                  R4      ;'       g    R4      ;'       g    RRP1                  T4      \3        T	4      T'       d   RMRT
;'       g    RT'       d   RMR4       R#   \
         d"   p\        P                  RT4        Rp?R# Rp?ii ; i  \
         d    Rp ELäi ; i  \*         d#   p\        P                  R
Yô4        Rp?EK“  Rp?ii ; i)a·  Boot-time relay self-provision: mint relay creds in-process, no human, no disk.

Fires when ``relay_url()`` is set and NO per-gateway secret is pinned: resolves the
identity token, POSTs ``/relay/provision`` for EACH fronted platform and sets
``GATEWAY_RELAY_ID`` / ``_SECRET`` / ``_DELIVERY_KEY`` in ``os.environ`` for
``register_relay_adapter()``. Creds live ONLY in process memory (never
``~/.hermes/.env``), so a hosted container re-provisions every boot; the
connector's rotation window covers a still-connected prior instance. The trigger
is deliberately NOT ``is_managed()`` (False on a NAS-hosted Fly agent): "pointed
at a connector without a pinned secret" is the real signal and self-guards (an
enrolled gateway has a PINNED secret -> skipped; no resolvable identity -> no-op).
Returns True iff it provisioned. NEVER raises: a failure logs and returns False so
the gateway still boots (the adapter then dials unauthenticated / is rejected).
Fz>relay self-provision skipped: GATEWAY_RELAY_SECRET already setzCrelay self-provision skipped: could not resolve identity token (%s)Nr)   rp   zgw-Úhermes)
rß   rà   ru   rY   r[   rá   râ   rÛ   rÜ   rÝ   zJrelay self-provision failed for platform=%s (%s); continuing with the restrv   rr   rä   ÚdeliveryKeyÚGATEWAY_RELAY_DELIVERY_KEYzXrelay self-provision failed for ALL platforms (%s); gateway will boot without relay authrQ   c              3  ó*   "  € T F	  w  rVx € K  	  R # 5irÄ   r	   )rÅ   rV   r`   s   &  r   rÇ   Ú'self_provision_relay.<locals>.<genexpr>R  s   é € Ð.¡:™4˜1•Q£:ùs   ‚zýrelay self-provision withheld credentials for ALL platforms (%s): the connector holds a binding for gateway_id=%s this caller could not prove ownership of; gateway will boot without relay auth. Recover with POST /relay/rotate or pin GATEWAY_RELAY_SECRETzfrelay self-provisioned (gateway_id=%s tenant=%s platforms=%s routes=%d inbound=%s instance=%s wake=%s)ÚtenantÚ?Úyeszoutbound-onlyÚunboundÚnoneT)rM   rw   rg   Úinfor  r   rh   r\   ÚsocketÚgethostnamer,   r*   r+   r   r|   rƒ   r‹   r�   r˜   rù   r¢   rð   rU   r&   ÚjoinÚlen)Údial_urlÚexisting_idÚexisting_secretrà   r÷   Ú
identitiesÚhostru   Úendpointrâ   rÛ   rÜ   rÝ   ÚprovisionedÚresultrY   r[   s                    r   Úself_provision_relayr0  þ  sß  € ô ‹{€HßÙä#8Ó#:Ñ €Kß—Ü�‰ÐTÔUÙðÜ4Ó6ˆô
 +Ó,€JðÜ×!Ò!Ó#×)Ñ)Ó+ˆô —‘—‘Ð 2°BÓ7×=Ñ=Ó?×[Ð[ÀSÈ×IYÐIYÐQYÐHZÐC[€JÜÓ€HÜ!Ó#€JÜ#Ó%€KÜÓ€HÜ%Ó'€Lð  €KØ€FÜ&Ñˆ�&ð	Ü$Ü,¨XÓ6À\Ø%ÀÐZbØ%ÈØ)ô	ˆFð 	×Ñ˜8Ô$ð �:‰:�h×Ô¬¯
©
¯©Ð7M×(NÔ(NÜ-0°·±¸KÓ1H×1VÐ1VÈJÓ-WŒB�J‰JÐ)Ñ*Ü14°V¸HÕ5EÓ1FŒB�J‰JÐ-Ñ.Ü7:¸6¿:¹:ÀmÓ;T×;ZÐ;ZÐXZÓ7[ŒB�J‰JÐ3Ô4ñ; '÷> Ü�‰ØfØ�H‰HÑ.¡:Ó.Ó.ô	
ñ ä�:‰:�>‰>Ð0×1Ò1ô 	�‰ð#ð �H‰H�[Ó! :ô	
ñ ä
‡K�KØpÜ
�
‰
�‰Ð)¨:Ó6ÜˆF�J‰J�xÓ ×&Ð& BÓ'×.Ð.¨3Ø�‰�ÓÜˆJ‹ß‰˜Ø× Ð �yß‰˜vô	ñ øôq ô Ü�‰Ð\Ð^aÔbÝûðûô ô Ø‹ðûô0 ô 	Ü�N‰NØ\Øôö ûð	úsB   Á	
L& Á#M ÄM)Ì&MÌ1MÍMÍM&Í%M&Í)NÍ4NÎNc          
     ó,   € V ^8„  d   QhRRRRRRRRRR	/# )
r   Ú
policy_urlr&   r¥   Úpolicyr   r§   r¨   r   Úintr	   )r
   s   "r   r   r   s  s7   € ÷ Pñ P ð P¨Cð P¸ð PÈð PÐdgñ Pr   c                óŒ  €  \        WW#4      ;_uu_ 4       p\        VP                  4      uuRRR4       #   + '       g   i     R# ; i  \        P                  P
                   d    p\        TP                  4      u Rp?# Rp?i\        P                  P                   d   p\        RTP                   24      ThRp?ii ; i)a  POST the relevance policy to ``/relay/policy``; return the HTTP status.
Authenticated with the gateway's own upgrade token, so the connector resolves
``{tenant, instanceId}`` from its stored secret record, never the body. Raises
RuntimeError on transport failure.Nrë   )
r¼   r4  Ústatusrµ   rê   rï   rñ   rò   rð   ró   )r2  r¥   r3  r§   rõ   r÷   s   $$$$  r   Ú_post_policyr7  s  s‡   € ð
PÜ˜
¨6×;Ô;¸tÜ�t—{‘{Ó#÷ <×;×;Ó;ûä�<‰<×!Ñ!ô Ü�3—8‘8‹}ÕûÜ�<‰<× Ñ ô PÜÐ8¸¿¹¸ÐEÓFÈCÐOûðPúsI   ‚A
 –6«
A
 ¶A	ÁA
 ÁA
 Á
CÁ)BÁ=CÂ CÂ$CÂ%B>Â>Cc               ó   € V ^8„  d   QhRR/# r6   r	   )r
   s   "r   r   r   �  s   € ÷ 7ñ 7˜4ñ 7r   c                 óÚ  € \        4       p V '       g   R# \        4       w  rV'       d	   V'       g   R#  ^ RIHp V! W4      p\        T R4      pRp\        4        F®  w  r‰\        T4      p
T
f   K   \        YdT
R7      pT^È8X  dm   Rp\
        P                  R	T
P                  R
4      T
P                  R4      \        T
P                  R4      ;'       g    . 4      T
P                  R4      4       K—  \
        P                  RTT4       K°  	  T#   \         d"   p\
        P                  RT4        Rp?R# Rp?ii ; i  \         d#   p\
        P                  RY…4        Rp?EK  Rp?ii ; i)aÁ  Declare this gateway's relevance policy to the connector, per fronted platform,
at boot AFTER the per-gateway secret is resolved. The connector enforces it on
delivery, so the SAME mention-gating / free-response / allow-bots behavior the
agent applies directly also governs relay delivery, and excluded traffic never
wakes a scaled-to-zero agent. Re-declared every boot (idempotent full replace); a
platform with nothing non-default is skipped; one failed POST doesn't block the
others. NEVER raises / blocks boot: relevance is an optimization layered on the
authorization gate, so a failure just leaves the connector's prior policy.
Returns True iff the connector accepted at least one policy (HTTP 200).F)Úmake_upgrade_tokenzQrelay policy declaration failed to build token (%s); connector keeps prior policyNz/relay/policy)r2  r¥   r3  z@relay policy declaration failed for platform=%s (%s); continuingTzSrelay policy declared (platform=%s require_address=%s free_scopes=%d allow_bots=%s)rY   rÌ   rÍ   rÎ   z_relay policy declaration for platform=%s returned HTTP %s; connector keeps prior/default policy)rM   rw   Úgateway.relay.authr:  r   rg   rh   rŸ   r\   rÚ   r7  r#  r   r'  )r(  ru   rv   r:  r¥   r÷   r2  Úany_declaredrY   rÔ   r3  r6  s               r   Úsend_relay_policyr=  �  sF  € ô ‹{€HßÙä.Ó0Ñ€JßŸVáðÝ9á" :Ó6ˆô
   ¨/Ó:€JØ€LÜ6Ö8ÑˆÜ'¨Ó1ˆØŠ>Ùð	Ü!¨ZÈVÔTˆFð �SŒ=ØˆLÜ�K‰KØeØ—
‘
˜:Ó&Ø—
‘
Ð+Ó,Ü�F—J‘JÐ3Ó4×:Ð:¸Ó;Ø—
‘
Ð+Ó,öô �N‰NØqØØöñ+ 9ð4 ÐøôA ô Ü�‰ÐjÐloÔpÝûðûô ô 	Ü�N‰NØRÐT\ôö ûð		ús/   ´D Á1D=ÄD:ÄD5Ä5D:Ä=E*ÅE%Å%E*c               ó$   € V ^8„  d   QhRRRRRR/# )r   Úforcer7   r¤   r0   r   r	   )r
   s   "r   r   r   »  s!   € ÷ ?ñ ? $ð ?°]ð ?Èdñ ?r   c                ó  aaaaa	a
€ \        4       '       d   R# Ve   TM	\        4       o
V '       g   S
'       g   R# ^ RIHpHp ^ RIHo ^ RIHoH	o \        4       w  o	oVVVVV	V
3R lpVP                  V! RRVR R	R
R7      4       R# )aU  Register the generic ``relay`` platform when a relay URL is configured (or
``force=True`` for tests: transport-less adapter). Neither overrides an
explicit profile disable. Returns True if registered.
With a URL the factory builds a live ``WebSocketRelayTransport``; the adapter
negotiates the real ``CapabilityDescriptor`` at ``connect()``.F)ÚPlatformEntryÚplatform_registry)ÚRelayAdapter)ÚCONTRACT_VERSIONÚCapabilityDescriptorc                ó    <€ S! SS
R RRRRRRR7	      pRpS'       d*   ^ RI Hp \        4       w  rEV! SS
S	\        4       VVRR	7      pS! WVR
7      # )ÚRelayi   FTÚplainÚchars)	Úcontract_versionrY   ÚlabelÚmax_message_lengthÚsupports_draft_streamingÚsupports_editÚsupports_threadsÚmarkdown_dialectÚlen_unitN)ÚWebSocketRelayTransport)r+  ru   Úupgrade_secretÚ	reconnect)Ú	transport)Úgateway.relay.ws_transportrR  rw   r\   )ÚconfigÚplaceholderrU  rR  ru   rS  rD  rE  rC  r[   rY   Úresolved_urls   &     €€€€€€r   Ú_factoryÚ(register_relay_adapter.<locals>._factoryÍ  sw   ø€ ñ +Ø-ØØØ#Ø%*ØØ"Ø$Øô

ˆð ˆ	ßÝJä)>Ó)@Ñ&ˆJÙ/ØØØô 5Ó6Ø%Ø-ð ôˆIñ ˜F¸9ÔEÐEr   r@   rG  c                 ó   € R # )Tr	   r	   r   r   Ú<lambda>Ú(register_relay_adapter.<locals>.<lambda>õ  s   € ™Tr   Úbuiltinu   ðŸ”Œ)ÚnamerK  Úadapter_factoryÚcheck_fnÚsourceÚemojiT)rH   rM   Úgateway.platform_registryrA  rB  Úgateway.relay.adapterrC  Úgateway.relay.descriptorrD  rE  rm   Úregister)r?  r¤   rA  rB  rZ  rD  rE  rC  r[   rY   rY  s   &&   @@@@@@r   Úregister_relay_adapterri  »  sx   ý€ ô !×"Ò"ÙØš/‘3¬y«{€Lß—\ÙçJÝ2ßOä.Ó0Ñ€Hˆf÷!Fò !FðF ×ÑÙØØØ$Ù!ØØô	
ô	ñ r   )rý   r  r  r	  rÄ   )FN)0Ú__doc__Ú
__future__r   r    re   Úloggingr*   Úrer$  Úurllib.errorrµ   Úurllib.parseÚurllib.requestÚtypingr   Ú	getLoggerrg   Úcompiler  r  r
  r   r   r#   r.   r4   rH   rM   r\   ra   rT   rm   rw   r|   rƒ   r‹   r�   r˜   rŸ   r¢   r¼   rÚ   rù   r  r0  r7  r=  ri  r	   r   r   Ú<module>rt     s2  ðñ
õ #ã Û Û Û 	Û 	Û Û Û Û Ý à	×	Ò	˜?Ó	+€ð —z’zðóÐ ð
 €ð A€	õ0õ4ò=õ&Gõ=õ
7õ:=õõ$Gõ
õ*õ
0õGõ<õQõGõõD5õ>õ8÷;ð|Hð "&ðHð #ðHð #'ðHð %÷HõVX õvrðjPÐP_÷ Põ7÷t?ñ ?r   