Ë
    âß²jO  ã                  ól   — d Z ddlmZ ddlmZmZ ddlmZmZ dd„Z	ddd„Z
ddd„Z	 	 	 	 	 	 dd	„Zdd
„Zy)zAFail-closed URL identity normalization for model/provider routes.é    )Úannotations)ÚAnyÚOptional)ÚurlsplitÚ
urlunsplitc                ó`  — t        | xs d«      }|syt        d„ |D «       «      r|S d|j                  dd«      d   v }	 t        |«      }|j                  }|j
                  r|s|S |j
                  j                  «       }d|v r+|j                  dd«      \  }}|j                  «       › d|› �}n|j                  «       }|j                  }	|j                  j                  dd«      d	   }
|
j                  d
«      sd|v rd
|› d�}|	�||	fdvr|› d|	› �}d|j                  v r$|j                  j                  dd«      d   › d|› �}|j                  }|j                  d«      r|s|dd	 }t        ||||j                   df«      }|r|j                   s|dz  }|S # t        t        f$ r |cY S w xY w)z<Canonicalize only proven-equivalent endpoint URL components.Ú c              3  ó8   K  — | ]  }t        |«      d k  –— Œ y­w)é    N)Úord)Ú.0Úchars     ú>/home/ubuntu/.hermes/hermes-agent/hermes_cli/route_identity.pyú	<genexpr>z+normalize_route_base_url.<locals>.<genexpr>   s   è ø€ Ò
- Œ3ˆt‹9˜ÕÑ
-ùs   ‚ú?ú#é   r   ú%ú@éÿÿÿÿú[ú:ú]N>   ©ÚhttpéP   ©Úhttpsi»  ú/)ÚstrÚanyÚsplitr   ÚhostnameÚschemeÚlowerÚportÚ	TypeErrorÚ
ValueErrorÚnetlocÚrsplitÚ
startswithÚpathÚendswithr   Úquery)Úbase_urlÚrawÚhad_query_delimiterÚparsedr#   r$   ÚaddressÚzoneÚhostr&   Ú
route_hostr,   Ú
normalizeds                r   Únormalize_route_base_urlr8   	   sÅ  € ä
ˆhŠn˜"Ó
€CÙØÜ
Ñ
-¨Ô
-Ô-Øˆ
Ø §¡¨3°Ó!2°1Ñ!5Ð5ÐðÜ˜#“ˆØ—?‘?ˆØ�}Š}¡HØˆJØ—‘×$Ñ$Ó&ˆØ�(‰?Ø$ŸN™N¨3°Ó2‰MˆG�TØ—m‘m“oÐ& a¨ vÐ.‰Dà—>‘>Ó#ˆDØ�{‰{ˆð —‘×%Ñ% c¨1Ó-¨bÑ1€JØ×Ñ˜SÔ! S¨D¡[Ø�4�&˜ˆ{ˆØÐ˜V T˜NÐ2PÑPØ��q˜˜ÐˆØ
ˆf�m‰mÑØ—-‘-×&Ñ& s¨AÓ.¨qÑ1Ð2°!°D°6Ð:ˆØ�;‰;€DØ‡}�}�SÔÑ"5Ø�C�RˆyˆÜ˜V T¨4°·±¸rÐBÓC€JÙ 6§<¢<Ø�cÑˆ
ØÐøô ”zÐ"ò ØŠ
ðús   ¿&F Á&A%F ÆF-Æ,F-Nc                óP  — ddl m}m}m}m} ddlm}  |t        |xs d«      «      }|syt        | xs d«      j                  «       j                  «       }	 ||	«      }
|
dv ryt        |t        «      r|ni } ||	|j                  d«      xs i «      xs  ||	|j                  d	«      «      }|�!|j                  r ||j                  «      |k(  S  ||
d
¬«      }|�"|j                  r ||j                  «      |k(  ry|€|€yddlm}  |t        |«      «      }|€y ||«      |
k(  S )uJ  Whether ``model.base_url`` is *provider*'s own endpoint.

    ``True``: the host is the provider's registry/plugin endpoint or the endpoint of a
    ``providers:``/``custom_providers:`` entry that resolves to *provider*, or *provider* is bare
    ``custom``/``local`` (the URL *is* the route). ``False``: the host is another known provider's
    stock endpoint, or *provider* names a user entry with a different endpoint. ``None``: unknown
    host (a proxy, a LAN server) â€” nothing here can say whose it is. Offline: the registry lookup
    never fetches the models.dev catalog.
    r   )Úget_providerÚnormalize_providerÚresolve_custom_providerÚresolve_user_provider)Úbase_url_hostnamer	   N)ÚcustomÚlocalTÚ	providersÚcustom_providersF)Úallow_network)Ú_infer_provider_from_url)Úhermes_cli.providersr:   r;   r<   r=   Úutilsr>   r    Ústripr%   Ú
isinstanceÚdictÚgetr/   Úagent.model_metadatarD   )Úproviderr/   Úconfigr:   r;   r<   r=   r>   r5   r0   Ú	canonicalÚcfgÚ	user_pdefÚpdefrD   Úinferreds                   r   Úprovider_owns_routerS   /   s.  € ÷ vÓuÝ'áœS ¢¨RÓ0Ó1€DÙØÜ
ˆhŠn˜"Ó
×
#Ñ
#Ó
%×
+Ñ
+Ó
-€CÙ" 3Ó'€IØÐ'Ñ'ð Ü˜v¤tÔ,‰&°"€CÙ% c¨3¯7©7°;Ó+?Ò+EÀ2ÓFò *ÑJaØˆS�W‰WÐ'Ó(óK*€IàÐ ×!3Ò!3Ù  ×!3Ñ!3Ó4¸Ñ<Ð<Ù˜	°Ô7€DØÐ˜DŸMšMÑ.?ÀÇÁÓ.NÐRVÒ.VØØ€|˜	Ð)ØÝ=Ù'¬¨H«Ó6€HØÐØÙ˜hÓ'¨9Ñ4Ð4ó    c                ó4  — t        | t        «      si dfS t        | j                  d«      xs d«      j	                  «       }|rt        |||«      nd}|ri dfS |€i dfS dD �ci c](  }| j                  |«      dvsŒ|| j                  |«      “Œ* }}|dfS c c}w )us  Pop the route keys (``base_url``, ``api_mode``) a previous provider left in ``model:``
    when the block is re-pointed at *provider* without a fresh route (``hermes config set
    model.provider``). Mirrors what a persisted ``/model`` switch writes: the route is synced to
    the target, never carried over. Returns ``(popped {key: old value}, unverified)`` where
    ``unverified`` is True when a base_url of unknown ownership was kept â€” the caller should say so.
    A base_url that belongs to *provider* is kept together with its api_mode; with no base_url the
    api_mode alone is wire state of the old route and goes.Fr/   r	   T)r/   Úapi_mode)Nr	   )rH   rI   r    rJ   rG   rS   Úpop)Ú	model_cfgrL   rM   r/   ÚownedÚkÚpoppeds          r   Údrop_stale_model_router\   V   sª   € ô �i¤Ô&Ø�5ˆyÐÜ�9—=‘= Ó,Ò2°Ó3×9Ñ9Ó;€HÙ?GÔ ¨(°FÔ;ÈU€EÙØ�5ˆyÐØ€}Ø�4ˆxˆØ+CÖj aÀyÇ}Á}ÐUVÓGWÐ_iÒGiˆa�—‘˜qÓ!Ñ!Ðj€FÐjØ�5ˆ=Ðùò ks   Á"BÁ;Bc                óÄ   — t        | xs d«      j                  «       } | r!| t        |xs d«      j                  «       k7  ry	 ddlm}  |||||«      S # t        $ r Y yw xY w)zôTrue when a configured ``model.context_length`` pin no longer matches its runtime route.
    Fail-closed: any error during route comparison returns ``True`` (drop the pin) so a stale window
    never silently inflates the compression threshold.r	   Tr   )Ú_context_route_mismatch)r    rG   Úagent.agent_initr^   Ú	Exception)Úconfigured_modelÚactive_modelÚconfigured_base_urlÚactive_base_urlÚconfigured_providerÚactive_providerr^   s          r   Úshould_clear_context_pinrg   j   sm   € ô
 Ð+Ò1¨rÓ2×8Ñ8Ó:ÐÙÐ,´°LÒ4FÀBÓ0G×0MÑ0MÓ0OÒOØðÝ<Ù&Ð':¸OÐM`ÐbqÓrÐrøÜò Ùðús   ÁA Á	AÁAc               ‡  óT   K  — ddl } |j                  t        g| ¢­Ž ƒ d{  –—† S 7 Œ­w)u×   ``should_clear_context_pin`` on a worker thread so async gateway handlers never run it on the
    event loop â€” the resolution chain is cache-only (``allow_network=False``) but can still do
    cold-start disk I/O.r   N)ÚasyncioÚ	to_threadrg   )Úargsri   s     r   Úshould_clear_context_pin_asyncrl   y   s*   è ø€ ó Ø"�×"Ñ"Ô#;ÐC¸dÒC×CÐCÐCús   ‚(¡&¢()r/   r   Úreturnr    )N)rL   r   r/   r   rM   r   rm   zOptional[bool])rX   r   rL   r   rM   r   rm   z'tuple[dict[str, Any], bool]')ra   r   rb   r   rc   r   rd   r   re   r   rf   r   rm   Úbool)rk   r   rm   rn   )Ú__doc__Ú
__future__r   Útypingr   r   Úurllib.parser   r   r8   rS   r\   rg   rl   © rT   r   ú<module>rt      sE   ðÙ Gå "ç  ß -ó#ôL$5ôNð(Ø25ðØHKðØPTóôDrT   