Ë
    Pä²j- ã                   ó  — U d 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mZmZmZmZ ddlmZ ddlZerddlZddlmZmZmZmZ ddlmZmZ ddlm Z   ejB                  e"«      Z#d	„ Z$d
e%fd„Z&�d de%de'e%z  fd„Z(	 ddl)m*Z+  e-d„  e+«       D «       «      Z.e-e%   e/d<    ej`                  dejb                  «      Z2 ejf                  d«      Z4de%de%fd„Z5i a6ee%ee%ef   f   e/d<   da7e8e/d<   dZ9i Z:eee%e%f   ee%ee%ef   f   f   e/d<   i Z;eee%e%f   e8f   e/d<   dZ<dZ=dZ>i Z?ee%e@f   e/d <   d!ZAi ZBee%e8f   e/d"<   �dde%d#e%fd$„ZCde%dee%   fd%„ZDde%ddfd&„ZEde%de'fd'„ZFd(eGde%ddfd)„ZHd(eGde'fd*„ZIdZJd
e%de
fd+„ZKd,e
dee%ef   fd-„ZLd,e
d.e%d/e8d0e%d1e%dee   fd2„ZMd3d4œd,e
d.e%d5ed/e8d0e%d1e%d6e%d7e'ddfd8„ZNde
fd9„ZOd:e%d.e%dee   fd;„ZPd:e%d.e%d5eddfd<„ZQde
fd=„ZRdee8   fd>„ZSdee%ee%ef   f   fd?„ZTd@ee%ee%ef   f   ddfdA„ZUde
fdB„ZVdCe%deee%ee%ef   f      fdD„ZWdCe%dEee%ee%ef   f   ddfdF„ZXg dG¢ZYeYd   ZZ e[«       Z\e[e/dH<   de%de%ddfdI„Z]dJZ^d!Z_i Z`ee@e@f   e/dK<   dZai Zbee@e8f   e/dL<   i dMdN“dOdN“dPdN“dQdN“dRdN“dSdN“dTdN“dUdN“dVdN“dWdN“dXdN“dYdN“dZd[“d\d]“d^d]“d_d]“d`d]“i dad]“dbd]“dcd]“ddd]“dedf“dgdf“dhd]“didj“dkdj“dldf“dmdn“dodj“dpdq“drds“dtds“duds“dvdw“¥i dxdy“dzdN“d{dN“d|dN“d}dN“d~dN“ddN“d€dj“d�dw“d‚dq“dƒdq“d„dq“d…dN“d†dN“d‡dq“dˆdq“d‰dN“¥i dŠd‹“dŒd‹“d�dw“dŽdN“d�d�“d‘d’“d“d’“d”dq“d•dq“d–dq“d—dq“d˜dq“d™dq“dšds“d›d�“dœd�“džd�“¥i dŸd�“d d�“d¡d�“d¢dw“d£d�“d¤d�“d¥d[“d¦d§“d¨ds“d©ds“dªdy“d«d¬“d­d¬“d®d§“d¯d§“d°dN“d±ds“¥i d²dw“d³dw“d´dw“dµdq“d¶d‹“d·d‹“d¸dw“d¹dº“d»d¼“d½d¾“d¿dq“dÀd‹“dÁd‹“dÂdq“dÃdq“dÄd‹“dÅdN“¥i dÆdw“dÇd‹“dÈd‹“dÉd‹“dÊd‹“dËdw“dÌdw“dÍdº“dÎd‹“dÏd‹“dÐd‹“dÑd�“dÒd‹“dÓdq“dÔdq“dÕdq“dÖdq“¥dqdqd‹d‹d�d×œ¥ZcdØZdde%de'fdÙ„Ze ej`                  dÚ«      Zfde%de'fdÛ„Zgde%de'fdÜ„ZhdÝZidÞZjdßZkdàZlde%de%fdá„Zm�d dâendee%e%f   fdã„Zode%de'fdä„Zpi 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þ“dÿdp“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“�d�d“¥Zqee%e%f   e/�d<   	  e+«       D ])  Zrerjç                  «       ZtetsŒeteqvsŒerjê                  eqet<   Œ+ 	 de%dee%   f�d„Zv	 �dde%de%�de%de%f�d „Zwde%de'f�d!„Zxde%de%f�d"„Zyde%de%f�d#„Zz�d$Z{ ej`                  �d%�d&jù                   e}ejü                  e{«      «      › �d'�«      Zd.e%�d(e%de'f�d)„Z€�d*ee%e�f   �d(e%deee%e�f      f�d+„Z‚d�d,œd@ee%ef   �d-e'�d.ee�   dee�   f�d/„Zƒdñ�d0�d1hh �d2£dqf�d�d3h�d4hd‹ffZ„de%de%dee�   f�d5„Z…de%�de%de'f�d6„Z†�de%de%�d7e‡dz  de'f�d8„Zˆde%de%�d9e��de%ddf
�d:„Z‰de%de%�d;e�ddf�d<„ZŠde%de%dâe%�de%dee�   f
�d=„Z‹�d de%de%�d>e�dâe%de�f
�d?„ZŒde%de'f�d@„Z��dAe%de%f�dB„ZŽ�d de%dâe%dee%   f�dC„Z�d5ef�dD„Z��dd5e�d.e��dEe�dee�   f�dF„Z‘�dGee%ef   �dHe@e%�dIf   dee�   f�dJ„Z’�dGee%ef   dee�   f�dK„Z“�dGee%ef   dee�   f�dL„Z”�dM�dN�dNdNdN�dOœZ•�dPZ–�dQZ—�dRee%ef   �dSedee%ef   f�dT„Z˜�dGee%ef   dee%ef   f�dU„Z™dEee%ee%ef   f   �dVe%�dWee%ef   ddf�dX„Zš�d�dYe'dee%ee%ef   f   f�dZ„Z›dee%ef   �dVe%�d[ee�   dee%ef   f�d\„Zœdee%ef   dee�   f�d]„Z�dCe%�d^ee%e%f   dee%ee%ef   f   f�d_„ZždEee%ee%ef   f   �d`e%�d^ee%e%f   ddf�da„ZŸdCe%dâendee%e%f   f�db„Z �dcee%e%f   dEee%ee%ef   f   dee%ee%ef   f   f�dd„Z¡�dGee%ef   dee%ee%ef   f   f�de„Z¢�dde%dâe%�dYe'dee%ee%ef   f   f�df„Z£�d de%de%dâe%dee�   f�dg„Z¤de
f�dh„Z¥de¦f�di„Z§dee%e�f   f�dj„Z¨�ddEee%e�f   �dke¦dz  ddf�dl„Z©de%de%de%f�dm„Zªd�dnœde%de%�d;e��doe%ddf
�dp„Z«�d de%de%�d;e��de%ddf
�dq„Z¬d3�drœde%de%�dke'dee�   f�ds„Z­de%de%ddf�dt„Z®�due�dee�   f�dv„Z¯�dwe%dee�   f�dx„Z°�dwe%�dye�dee�   f�dz„Z± ej`                  �d{«      Z²�d|e%dee�   f�d}„Z³�dwe%dee�   f�d~„Z´�dZµ�d€Z¶�d�Z·�d|e%deee�e�f      f�d‚„Z¸�dƒe%�d„e@de'f�d…„Z¹�dwe%de'f�d†„Zº�d‡e%�dˆe%de'f�d‰„Z»�dd3�dŠœ�d‹e%dâe%�dŒe%�d�e8�dŽe'deee%ef      f�d�„Z¼de%dâe%de'f�d�„Z½�d de%de%dâe%dee�   f�d‘„Z¾�d de%de%dâe%dee'   f�d’„Z¿�d“e@�d”eg ee�   f   dee�   f�d•„ZÀ�d de%de%dâe%dee�   f�d–„ZÁ�d de%de%dâe%dee�   f�d—„ZÂde%de'f�d˜„ZÃde%de'f�d™„ZÄ e-h �dš£«      ZÅde%�d>e�de'f�d›„ZÆde%de'f�dœ„ZÇde%de'f�d�„ZÈ�d de%de%dâe%dee�   f�dž„ZÉd5edee�   f�dŸ„ZÊ�d e%de%dee�   f�d¡„ZË�d‹e%de%dee�   f�d¢„ZÌ�d‹e%de%dee�   f�d£„ZÍ�d de%de%dâe%dee�   f�d¤„ZÎde%de%f�d¥„ZÏde%de%dâedee�   f�d¦„ZÐi d\�d§“d^�d§“d_�d§“d`�d§“�d¨�d§“�d©�d§“�dª�d§“didj“�d«�d§“dg�d§“dc�d§“db�d§“da�d§“�d¬�d§“dd�d§“dh�d§“�d­�d§“dl�d§i¥ZÑee%e�f   e/�d®<   �d¯�d¯�d¯�d¯�d°œZÒee%e�f   e/�d±<   �d¯�d¯�d¯�d²œZÓee%e�f   e/�d³<   �d§ZÔ�d´ZÕ�dµZÖ e-h eÖ£dh’�d¬’d\’«      Z× ej`                  �d¶«      ZØdee%   de%f�d·„ZÙdee%   de'f�d¸„ZÚdee%   dee%   f�d¹„ZÛdee%   de'f�dº„ZÜdee%   de%f�d»„ZÝ�d¼e%de'f�d½„ZÞ�d¼e%dee�   f�d¾„Zßi Zàee%eee%e�f   e8f   f   e/�d¿<   i Záee%ee%e�f   f   e/�dÀ<   dZâ�dÁZã�dÂZä�dÃZå e@�dÄ„ eäeåfD «       «      Zæ�dÅee%gef   deee   ee�   f   f�dÆ„Zç�dÇe%de%f�dÈ„Zè�dÇe%deee%e�f   e'f   f�dÉ„Zé�d de%�dÇe%deee�   e%f   f�dÊ„Zê�dde%de%dâe%deee�   e%f   f�dË„Zëd�dÌœde%de%�d>e�dâe%dee�   f
�dÍ„Zìd.e@de'f�dÎ„Zí�d de%�de%de'f�dÏ„Zîde%de%dee�   f�dÐ„Zïde%de%dâe%�de%de�f
�dÑ„Zðde%de%dâe%�de%de�f
�dÒ„Zñde%�d7e‡dz  dee�   f�dÓ„Zòde%de%�de%�d7e‡dz  dee�   f
�dÔ„Zóde%de%dâe%�de%�dÕe%dee�   f�dÖ„Zô	 	 �dde%de%dâe%�d×e�dz  �de%�d7e‡dz  de�f�dØ„Zõ�dde%de%dâe%�d×e�dz  �de%�d7e‡dz  de�f�dÙ„Zö�dÚZ÷ ej`                  �dÛ«      Zø�dÜe%de'f�dÝ„Zù�dƒe%de�f�dÞ„Zú�dß�dàœ�dáeee%ef      �dâe'de�f�dã„Zû�däZü�dáeee%ef      deee%ef      f�då„Zýi Zþeeee‡e�e�f   f   e/�dæ<   �dçZÿd5e�dèe‡def�dé„�Z �dêe�dëe�de�f�dì„�Z�díe�dîe[de�f�dï„�Z e-h �dð£«      �Z�dêee%ef   �dñe�de�f�dò„�Z�dóedef�dô„�Z�dêee%ef   dee%ef   f�dõ„�Z�dêee%ef   de�f�dö„�Zdd�dß�d÷œ�dáeee%ef      �døe%�dùeeee%ef         �dâe'de�f
�dú„�Zi �Z	e¦e�ee�e%e%e�f   f   e/�dû<   �dü�Z
�dýede%f�dþ„�Z�dùeee%ef      de�f�dÿ„�Zy# e,$ r d„ Z+Y �ŒÝw xY w# e,$ r Y �	Œaw xY w(	  z¿Model metadata, context lengths, and token estimation utilities.

Pure utility functions with no AIAgent dependency. Used by ContextCompressor
and run_agent.py for pre-flight context checks.
é    N)ÚPath)ÚAnyÚCallableÚDictÚListÚOptionalÚTupleÚTYPE_CHECKING)Úurlparse)Úatomic_json_writeÚatomic_yaml_writeÚbase_url_host_matchesÚbase_url_hostname)ÚOPENROUTER_MODELS_URLÚopenrouter_variant_base)ÚPERSISTENCE_ONLY_MESSAGE_FIELDSc                  óV   — dt        «       vrdd l} | t        «       d<   t        «       d   S )NÚrequestsr   )Úglobalsr   )Ú	_requestss    ú9/home/ubuntu/.hermes/hermes-agent/agent/model_metadata.pyÚ_ensure_requestsr   #   s(   € Øœ›Ñ"Û$Ø )Œ‹	�*ÑÜ‹9�ZÑ Ð ó    Únamec                 óJ   — | dk(  r
t        «       S t        dt        ›d| ›�«      ‚)Nr   zmodule z has no attribute )r   ÚAttributeErrorÚ__name__)r   s    r   Ú__getattr__r   *   s,   € ØˆzÒÜÓ!Ð!Ü
˜7¤8 ,Ð.@ÀÀÐIÓ
JÐJr   Ú Úbase_urlÚreturnc                 óx  — | rg	 ddl m}  || «      }|j                  d«      du ry|j                  d«      }t        |t        «      r#|r!t
        j                  j                  |«      r|S dD ]=  }t        j                  |«      }|sŒt
        j                  j                  |«      sŒ;|c S  y# t        $ r Y ŒNw xY w)a"  SSL ``verify`` for ``requests`` probes; mirrors ``agent.ssl_verify.resolve_httpx_verify``.
    Priority: per-provider ``ssl_verify: false`` -> per-provider ``ssl_ca_cert`` (else probes log
    spurious CERTIFICATE_VERIFY_FAILED while the httpx chat path succeeds) -> CA env vars -> certifi.r   )Ú get_custom_provider_tls_settingsÚ
ssl_verifyFÚssl_ca_cert)ÚHERMES_CA_BUNDLEÚREQUESTS_CA_BUNDLEÚSSL_CERT_FILET)
Úhermes_cli.configr#   ÚgetÚ
isinstanceÚstrÚosÚpathÚisfileÚ	ExceptionÚgetenv)r    r#   ÚtlsÚcaÚenv_varÚvals         r   Ú_resolve_requests_verifyr6   0   s«   € ñ ð		ÝJÙ2°8Ó<ˆCØ�w‰w�|Ó$¨Ñ-ØØ—‘˜Ó'ˆBÜ˜"œcÔ"¡r¬b¯g©g¯n©n¸RÔ.@Ø�	ð Oò ˆÜ�i‰i˜Ó ˆÚ”2—7‘7—>‘> #Õ&ØŠJðð øô ò 	Ùð	ús   „!B- ¦AB- Â-	B9Â8B9)Úlist_providersc                  ó   — g S ©N© r:   r   r   Ú_list_providersr;   J   s   € Øˆ	r   c              #   óz   K  — | ]3  }|j                   g|j                  ¢­D ]  }|j                  «       –— Œ Œ5 y ­wr9   )r   ÚaliasesÚlower)Ú.0ÚprofileÚvalues      r   ú	<genexpr>rB   M   sC   è ø€ ò /àØ—,‘,Ð1 §¡Ñ1ò/ð 	ð 
‡K�K‡Mð/Øñ/ùs   ‚9;Ú_PROVIDER_PREFIXESzE^(\d+\.?\d*b|latest|stable|q\d|fp?\d|instruct|chat|coder|vision|text)z100.64.0.0/10Úmodelc                 ó(  — d| vs| j                  d«      r| S | j                  dd«      \  }}	 ddlm}  ||j	                  «       j                  «       «      du}|r%t        j                  |j	                  «       «      s|S | S # t        $ r d}Y Œ6w xY w)z©Strip a registry-known provider prefix: ``"local:m"`` -> ``"m"``. Ollama ``model:tag``
    ids are preserved even when the model half is a provider name (``qwen:0.5b``).ú:Úhttpé   r   ©Úget_provider_profileNF)	Ú
startswithÚsplitÚ	providersrJ   Ústripr>   r0   Ú_OLLAMA_TAG_PATTERNÚmatch)rD   ÚprefixÚsuffixrJ   Úis_providers        r   Ú_strip_provider_prefixrT   X   s‘   € ð �%Ñ˜5×+Ñ+¨FÔ3ØˆØ—[‘[  aÓ(�N€FˆFðÝ2Ù*¨6¯<©<«>×+?Ñ+?Ó+AÓBÈ$ÐNˆñ Ô.×4Ñ4°V·\±\³^ÔDØˆØ€Løô	 ò ØŠðús   ®,B ÂBÂBÚ_model_metadata_cacheÚ_model_metadata_cache_timei  Ú_endpoint_model_metadata_cacheÚ#_endpoint_model_metadata_cache_timei,  g      ¬@g     Àr@Ú_endpoint_probe_path_cacheg      >@Ú_endpoint_blackhole_cacheÚschemec                 óR   — t        | «      }|syt        d|v r|«      S |› d|› �«      S )zW``urlparse`` of the normalized URL (``scheme`` prepended when absent); None when empty.Nz://)Ú_normalize_base_urlr   )r    r[   Ú
normalizeds      r   Ú_parse_base_urlr_   �   s7   € ä$ XÓ.€JÙØÜ %¨:Ñ"5�JÓVÐV¸f¸XÀSÈÈÐ;UÓVÐVr   c                 óº   — 	 t        | «      }|�|j                  sy|j                  › d|j                  xs |j                  dk(  rd› �S d› �S # t        $ r Y yw xY w)z[``host:port`` key (None without a host) so every probe path for one server shares an entry.NrF   Úhttpsé»  éP   )r_   ÚhostnameÚportr[   r0   )r    Úparseds     r   Ú_endpoint_host_keyrg   ‰   sh   € ðÜ  Ó*ˆØˆ> §¢ØØ—/‘/Ð" ! F§K¡KÒ$\¸6¿=¹=ÈGÒ;S°CÐ#]Ð^Ð^ÐY[Ð#]Ð^Ð^øÜò Ùðús   ‚A œ-A Á
A Á	AÁAc                 óŒ   — t        | «      }|�7t        j                  «       t        |<   t        j                  d|t        «       yy)zARecord that a probe to ``base_url`` timed out during TCP connect.NuF   Endpoint %s timed out connecting â€” skipping further probes for %.0fs)rg   ÚtimeÚ	monotonicrZ   ÚloggerÚdebugÚ_ENDPOINT_BLACKHOLE_TTL_SECONDS)r    Úkeys     r   Ú_note_endpoint_blackholedro   ”   sB   € ä
˜XÓ
&€CØ
€Ü)-¯©Ó)9Ô! #Ñ&Ü�‰Ð]Ð_bô  eDõ  	Eð r   c                 ó²   — t         dk  ryt        | «      }|�t        j                  |«      nd}|€yt	        j
                  «       |z
  t         k\  rt        |= yy)zXTrue if a recent probe to ``base_url`` timed out during TCP connect (cache lookup only).r   FNT)rm   rg   rZ   r*   ri   rj   )r    rn   Úseens      r   Ú_endpoint_blackholedrr   œ   sY   € ä&¨!Ò+ØÜ
˜XÓ
&€CØ14°Ô$×(Ñ(¨Ô-Àd€DØ€|ØÜ�‰Ó˜4ÑÔ$CÒCÜ% cÐ*ØØr   Úexcc                 ó2   — t        | «      rt        |«       yy)z?Blackhole ``base_url`` when ``exc`` is a connect-phase timeout.N)Ú_is_connect_timeoutro   )rs   r    s     r   Ú_note_if_connect_timeoutrv   ª   s   € ä˜3ÔÜ! (Õ+ð  r   c                 óf   — 	 ddl }ddlm} t        | |j                  |f«      S # t        $ r Y yw xY w)z�True for connect-phase timeouts raised by httpx or requests. Read timeouts are
    excluded: the server accepted the connection, the opposite of a blackhole.r   N)ÚConnectTimeoutF)ÚhttpxÚrequests.exceptionsrx   r+   r0   )rs   ry   rx   s      r   ru   ru   °   s7   € ðÛÝ6Ü˜# × 4Ñ 4°nÐEÓFÐFøÜò Ùðús   ‚!$ ¤	0¯0c                 ó(   — ddl m}  |«       dz  | z  S )Nr   ©Úget_hermes_homeÚcache©Úhermes_constantsr}   )r   r}   s     r   Ú_cache_filer�   À   s   € Ý0ÙÓ˜wÑ&¨Ñ-Ð-r   r.   c                 óÈ   — 	 | j                  dd¬«      5 }t        j                  |«      }ddd«       t        t        «      r|S i S # 1 sw Y   ŒxY w# t
        $ r i cY S w xY w)z4JSON object at ``path``, or {} when missing/invalid.Úrúutf-8©ÚencodingN)ÚopenÚjsonÚloadr+   Údictr0   )r.   ÚfÚdatas      r   Ú_load_json_dictr�   Å   sd   € ðØ�Y‰Y�s WˆYÓ-ð 	 °Ü—9‘9˜Q“<ˆD÷	 ä! $¬Ô-ˆtÐ5°2Ð5÷	 ð 	 ûô ò ØŠ	ðús-   ‚A •A«A ÁA ÁAÁA ÁA!Á A!rn   ÚttlÚts_keyÚ	value_keyc                óÐ   — t        | «      j                  |«      }t        |t        «      sy	 t	        j                  «       t        ||   «      z
  |k\  ry||   S # t        $ r Y yw xY w)z[Fresh (< ``ttl`` seconds) ``value_key`` of the ``key`` entry in a TTL memo file, else None.N)r�   r*   r+   rŠ   ri   Úfloatr0   )r.   rn   rŽ   r�   r�   Úentrys         r   Ú_ttl_memo_getr”   Ï   se   € ä˜DÓ!×%Ñ% cÓ*€EÜ�eœTÔ"ØðÜ�I‰I‹Kœ%  f¡Ó.Ñ.°3Ò6ØØ�YÑÐøÜò Ùðús   ­&A ÁA Á	A%Á$A%F)Úts_firstrA   Úwhatr•   c                ó’  — 	 t        j                   «       }t        | «      j                  «       D �	�
ci c];  \  }	}
t        |
t        «      sŒ|t        |
j                  |d«      «      z
  |k  sŒ9|	|
“Œ= }}	}
|r||||in||||i||<   t        | |dd¬«       yc c}
}	w # t        $ r!}t        j                  d||«       Y d}~yd}~ww xY w)zKWrite ``key`` into a TTL memo file, dropping expired siblings. Best-effort.r   ©ú,rF   ©ÚindentÚ
separatorszFailed to save %s: %sN)ri   r�   Úitemsr+   rŠ   r’   r*   r   r0   rk   rl   )r.   rn   rA   rŽ   r�   r�   r–   r•   ÚnowÚkÚvrŒ   Úes                r   Ú_ttl_memo_putr¢   Ü   sÎ   € ð7Ü�i‰i‹kˆÜ!0°Ó!6×!<Ñ!<Ó!>÷  A™˜˜AÄ*ÈQÔPTÕBUÐ[^ÔafÐgh×glÑglÐmsÐuvÓgwÓaxÑ[xÐ|ÓZ��1‘ð  Aˆñ  AÙ7?�V˜S )¨UÑ3ÀiÐQVÐX^Ð`cÐEdˆˆS‰	Ü˜$ ¨Q¸:ÖFùó Aøô ò 7Ü�‰Ð,¨d°A×6Ñ6ûð7ús4   ‚0B ²BÁ!BÁ-BÁ2#B ÂB Â	CÂ%CÃCc                  ó   — t        d«      S )Nzlocal_endpoint_probes.json©r�   r:   r   r   Ú_local_probe_disk_cache_pathr¥   ç   s   € ÜÐ3Ó4Ð4r   Úkindc                 óD   — t        t        «       | › d|› �t        dd¬«      S )z8Return a fresh cached value for ``kind:key``, else None.rF   ÚtsrA   ©r�   r�   )r”   r¥   Ú_LOCAL_PROBE_DISK_TTL_SECONDS)r¦   rn   s     r   Ú_local_probe_disk_getr«   ë   s0   € äÔ5Ó7¸D¸6ÀÀ3À%¸ÔJgÐptð  AHô  Ið  Ir   c           	      óJ   — t        t        «       | › d|› �|t        ddd¬«       y)zEPersist a successful probe result. Best-effort; prunes stale entries.rF   r¨   rA   zlocal probe disk cache)r�   r�   r–   N)r¢   r¥   rª   )r¦   rn   rA   s      r   Ú_local_probe_disk_putr­   ð   s3   € äÔ.Ó0°T°F¸!¸C¸5°/À5ÔJgÐptð  AHð  Ogö  hr   c                  ó   — t        d«      S )z1Path to the OpenRouter model metadata disk cache.zopenrouter_model_metadata.jsonr¤   r:   r   r   Ú_get_model_metadata_cache_pathr¯   õ   s   € äÐ7Ó8Ð8r   c                  ó¢   — 	 t        j                   «       t        «       j                  «       j                  z
  } | dk\  r| S dS # t        $ r Y yw xY w)z;Disk-cache age in seconds, or None if freshness is unknown.r   N)ri   r¯   ÚstatÚst_mtimer0   )Úages    r   Ú&_model_metadata_disk_cache_age_secondsr´   ú   sM   € ðÜ�i‰i‹kÔ:Ó<×AÑAÓC×LÑLÑLˆØ˜Q’hˆsÐ( DÐ(øÜò Ùðús   ‚=A Á A Á	AÁAc                  ó–  — 	 t        «       j                  dd¬«      5 } t        j                  | «      }ddd«       t	        t
        «      r>|j                  «       D ��ci c]"  \  }}t	        |t
        «      sŒt        |«      |“Œ$ c}}S i S # 1 sw Y   ŒYxY wc c}}w # t        $ r"}t        j                  d|«       i cY d}~S d}~ww xY w)zBProcessed OpenRouter metadata cache from disk ({} on any failure).rƒ   r„   r…   Nz7Failed to load OpenRouter model metadata disk cache: %s)r¯   r‡   rˆ   r‰   r+   rŠ   r�   r,   r0   rk   rl   )r‹   rŒ   rn   rA   r¡   s        r   Ú_load_model_metadata_disk_cacher¶     s¦   € ðÜ+Ó-×2Ñ2°3ÀÐ2ÓIð 	 ÈQÜ—9‘9˜Q“<ˆD÷	 ä^hÐimÔosÔ^t°$·*±*³,×Z¡J C¨Ä*ÈUÔTXÕBY”�C“˜%‘ÓZÐ|Ðz|Ð|÷	 ð 	 üãZøÜò Ü�‰ÐNÐPQÔRØ�	ûðúsK   ‚B �B³+B ÁBÁ7BÂB Â	B ÂBÂB Â	CÂ&CÂ=CÃCrŒ   c                 óŒ   — 	 t        t        «       | dd¬«       y # t        $ r }t        j	                  d|«       Y d }~y d }~ww xY w)Nr   r˜   rš   z7Failed to save OpenRouter model metadata disk cache: %s)r   r¯   r0   rk   rl   )rŒ   r¡   s     r   Ú_save_model_metadata_disk_cacher¸     s@   € ðSÜÔ8Ó:¸DÈÐWaÖbøÜò SÜ�‰ÐNÐPQ×RÑRûðSús   ‚ š	A£>¾Ac                  ó   — t        d«      S )zMOn-disk memo of remote ``/models`` probes (see ``_endpoint_disk_cache_get``).zendpoint_model_metadata.jsonr¤   r:   r   r   Ú!_get_endpoint_metadata_cache_pathrº     s   € äÐ5Ó6Ð6r   r^   c                 ób   — t        t        «       | t        dd¬«      }t        |t        «      r|S dS )a  Fresh cross-process memo of a remote ``/models`` probe (same TTL as in-memory): one-shot
    runs (``hermes -q``, cron) start cold and Nous bypasses the persistent context cache, so
    without this every launch paid the live probe. Local endpoints are never memoized.ÚatÚmodelsr©   N)r”   rº   Ú_ENDPOINT_MODEL_CACHE_TTLr+   rŠ   )r^   r½   s     r   Ú_endpoint_disk_cache_getr¿     s8   € ô Ô<Ó>À
ÔLeÐnrð  Gô  H€FÜ ¬Ô-ˆ6Ð7°4Ð7r   r~   c           
      óB   — t        t        «       | |t        dddd¬«       y)zLMemoize a successful remote ``/models`` probe; expired siblings are dropped.r¼   r½   z"endpoint model metadata disk cacheT)r�   r�   r–   r•   N)r¢   rº   r¾   )r^   r~   s     r   Ú_endpoint_disk_cache_putrÁ   "  s#   € äÜ)Ó+¨Z¸Ô@YØ˜xÐ.RÐ]aöcr   )é è é ô é ú  i }  i€>  i@  Ú_FALLBACK_WARNEDc                 ó”   — | |xs df}|t         vr8t         j                  |«       t        j                  d| |xs dt        d›«       yy)z£Warn once per model+endpoint that detection failed and the hard default is used,
    so small-context models (8K, 32K) don't silently get 256K and fail at the API.r   u‘   Could not determine context length for model %r (base_url=%s) â€” falling back to %s tokens. Set model.context_length in config.yaml to override.Údefaultr™   N)rÅ   Úaddrk   ÚwarningÚDEFAULT_FALLBACK_CONTEXT)rD   r    rn   s      r   Ú_warn_context_length_fallbackrË   /  sR   € ð �(’.˜bÐ
!€CØ
Ô"Ñ"Ü×Ñ˜SÔ!Ü�‰ðCà�8Ò(˜yÔ-EÀaÐ,Hõ	
ð #r   rÄ   Ú_LOCAL_CTX_PROBE_CACHEÚ_BEDROCK_PROBE_FAILURE_CACHEzclaude-fable-5é@B zclaude-fablezclaude-opus-5zclaude-sonnet-5zclaude-opus-4-8zclaude-opus-4.8zclaude-opus-4-7zclaude-opus-4.7zclaude-opus-4-6zclaude-sonnet-4-6zclaude-opus-4.6zclaude-sonnet-4.6Úclaudei@ úgpt-6-astrai� ú	gpt-6-solúgpt-6-terraú
gpt-6-lunaúgpt-5.6-lunaúgpt-5.6-terraúgpt-5.6-solzgpt-5.5zgpt-5.4-nanoi€ zgpt-5.4-miniúgpt-5.4zgpt-5.3-codex-sparkrÃ   zgpt-5.1-chatzgpt-5zgpt-4.1iü zgpt-4Úgeminii   zgemma-4rÂ   Úgemma4zgemma-4-31bzgemma-3i   Úgemmai    údeepseek-v4-proúdeepseek-v4.1-flashúdeepseek-v4-flashúdeepseek-chatúdeepseek-reasonerúdeepseek-flashÚdeepseekÚllamaúmuse-spark-1.3ú
muse-sparkÚinklingzqwen3.8-maxzqwen3.8-flashúqwen3.6-pluszqwen3.7-pluszqwen3-coder-pluszqwen3-coderi   z	qwen3-maxÚqwenú
minimax-m3Úminimaxi   zglm-5.3i   zglm-5.3-flashzglm-5.3:batchz
glm-5.3:uszglm-5.3-flash:batchzglm-5.3-flash:uszglm-5.3-flashxzglm-5.2zglm-5.2:freezglm-5.1zglm-5-turboi  zglm-5v-turbozglm-5zglm-4.7-flashzglm-4.7zglm-4.6vzglm-4.6Úglmzgrok-composerzgrok-build-latesti ¡ z
grok-buildzgrok-code-fastzgrok-2-visionúgrok-4-fasti€„ ú	grok-4.20úgrok-4.6úgrok-4.5úgrok-4.3zgrok-4zgrok-3zgrok-2Úgrokúkimi-k3Úkimizsolar-open2z
solar-pro3z
solar-pro2i   z
solar-minié €  úsolar-i   zhy4-previewzhy3-previewÚhy3zx-preview-fzox-alphazunion-alphaznemotron-3.5-lightningÚnemotronzlaguna-s-2.1zlaguna-xs-2.1ÚtrinityÚelephantzQwen/Qwen3.5-397B-A17BzQwen/Qwen3.5-35B-A3Bzdeepseek-ai/DeepSeek-V3.2zmoonshotai/Kimi-K2.5zmoonshotai/Kimi-K2.6zmoonshotai/Kimi-K2-ThinkingzMiniMaxAI/MiniMax-M2.5zXiaomiMiMo/MiMo-V2-Flashzmimo-v2.6-pro-ultraspeedzmimo-v2.6-prozmimo-v2.6-flashzmimo-v2-pro)zmimo-v2.5-proz	mimo-v2.5zmimo-v2-omnizmimo-v2-flashzzai-org/GLM-5)zgrok-3-minizgrok-4.20-multi-agentrï   rî   rí   c                 ó¸   ‡— | xs dj                  «       j                  «       j                  dd«      d   Št        ‰«      xr t	        ˆfd„t
        D «       «      S )zfAllowlist check (aggregator prefixes like ``x-ai/`` stripped); unknown Grok models get no effort dial.r   ú/rH   éÿÿÿÿc              3   ó@   •K  — | ]  }‰j                  |«      –— Œ y ­wr9   ©rK   )r?   rQ   r   s     €r   rB   z1grok_supports_reasoning_effort.<locals>.<genexpr>£  s   øè ø€ Òb¸&˜dŸo™o¨f×5Ñbùó   ƒ)rN   r>   ÚrsplitÚboolÚanyÚ_GROK_EFFORT_CAPABLE_PREFIXES©rD   r   s    @r   Úgrok_supports_reasoning_effortr     sK   ø€ àŠK�R×ÑÓ ×&Ñ&Ó(×/Ñ/°°QÓ7¸Ñ;€DÜ�‹:Òbœ#ÓbÔDaÔbÓbÐbr   z-^(?:ft:)?(?:gpt-3\.5|gpt-4(?![0-9])|chatgpt-)c                 ó¨   — | xs dj                  «       j                  «       j                  dd«      d   }t        t        j                  |«      «      S )z²True for an OpenAI model id (aggregator ``openai/`` prefix stripped) that rejects the
    Responses ``reasoning`` parameter outright, so callers send no ``reasoning`` key at all.r   rú   rH   rû   )rN   r>   rÿ   r   Ú_OPENAI_NON_REASONING_RErP   r  s     r   Úopenai_model_rejects_reasoningr  ®  sH   € ð ŠK�R×ÑÓ ×&Ñ&Ó(×/Ñ/°°QÓ7¸Ñ;€DÜÔ(×.Ñ.¨tÓ4Ó5Ð5r   c                 ó¼   — | xs dj                  «       j                  «       j                  dd«      j                  dd«      d   }|dk(  xs |j	                  d«      S )	z0Whether *model* is a Grok 4.6 family identifier.r   Ú_ú-rú   rH   rû   rí   z	grok-4.6-)rN   r>   Úreplacerÿ   rK   r  s     r   Úis_grok_46_familyr  µ  sU   € àŠK�R×ÑÓ ×&Ñ&Ó(×0Ñ0°°cÓ:×AÑAÀ#ÀqÓIÈ"ÑM€DØ�:ÑÒ= §¡°Ó!=Ð=r   )Úcontext_lengthÚcontext_windowÚcontext_sizeÚmax_context_lengthÚmax_position_embeddingsÚmax_model_lenÚmax_input_tokensÚmax_sequence_lengthÚmax_seq_lenÚn_ctx_trainÚn_ctxÚctx_size)Úmax_completion_tokensÚmax_output_tokensÚ
max_tokens)Ú	localhostz	127.0.0.1z::1z0.0.0.0)z.docker.internalz.containers.internalz.lima.internalc                 óH   — | xs dj                  «       j                  d«      S )Nr   rú   )rN   Úrstrip©r    s    r   r]   r]   Å  s    € ØŠN˜×!Ñ!Ó#×*Ñ*¨3Ó/Ð/r   Úapi_keyc                 ó4   — ddl m}  || «      }|rdd|› �iS i S )Nr   )Úmaterialize_probe_api_keyÚAuthorizationúBearer )Úagent.command_token_sourcer"  )r   r"  Útokens      r   Ú_auth_headersr'  É  s(   € ÝDÙ% gÓ.€EÙ38ˆO˜w u gÐ.Ð/Ð@¸bÐ@r   c                 óL   — t        | «      }t        |«      xr t        |d«       S )Núopenrouter.ai)r]   r   r   )r    r^   s     r   Ú_is_custom_endpointr*  Ï  s'   € Ü$ XÓ.€JÜ�
ÓÒVÔ$9¸*ÀoÓ$VÐ VÐVr   zapi.openai.comÚopenaizchatgpt.comúapi.anthropic.comÚ	anthropiczapi.z.aiÚzaizopen.bigmodel.cnzapi.moonshot.aizkimi-codingzapi.moonshot.cnzkimi-coding-cnzapi.kimi.comzapi.stepfun.aiÚstepfunzapi.stepfun.comzapi.arcee.aiÚarceezapi.minimaxzdashscope.aliyuncs.comÚalibabazdashscope-intl.aliyuncs.comzportal.qwen.aiz
qwen-oauthr)  Ú
openrouterz!generativelanguage.googleapis.comzinference-api.nousresearch.comÚnouszapi.deepseek.comzapi.githubcopilot.comÚcopilotz.githubcopilot.comzmodels.github.aizmodels.inference.ai.azure.comzapi.fireworks.aiÚ	fireworkszopencode.aizopencode-gozapi.x.aiÚxaizintegrate.api.nvidia.comÚnvidiazapi.xiaomimimo.comÚxiaomizxiaomimimo.comzapi.gmi-serving.comÚgmiúapi.novita.aiÚnovitaztokenhub.tencentmaas.comztencent-tokenhubzapi.lkeap.cloud.tencent.comztencent-tokenplanz
ollama.comúollama-cloudÚ_URL_TO_PROVIDERc                 óÖ   — t        | d«      }|€y|j                  j                  «       xs |j                  j                  «       }t        j                  «       D ]  \  }}||v sŒ|c S  y)zUmodels.dev provider name for a base URL (custom endpoints need no explicit provider).ra   N)r_   Únetlocr>   r.   r=  r�   )r    rf   ÚhostÚurl_partÚproviders        r   Ú_infer_provider_from_urlrC  ò  si   € ä˜X wÓ/€FØ€~ØØ�=‰=×ÑÓ Ò7 F§K¡K×$5Ñ$5Ó$7€DÜ.×4Ñ4Ó6ò Ñˆ�(Ø�tÒØŠOðð r   rB  c                 óæ   — | s| S |xs dj                  «       j                  «       dk(  xs t        |«      xr t        |«      dk(  }|s| S t	        | «      }|€| S t
        j                  d| |«       |S )uú  Strip an OpenRouter routing-variant suffix for catalog lookup.

    ``:nitro`` / ``:floor`` / ``:exacto`` / ``:online`` are request-time
    routing modifiers, NOT catalog entries â€” OpenRouter's ``/models`` lists
    only the base id, and a variant shares the base model's context window.
    Without this, every lookup below misses and the resolver falls through to
    a generic family default (``x-ai/grok-4.6:nitro`` â†’ the 131K ``grok``
    catch-all instead of its real 2M window).

    Only the id used for LOOKUP is rewritten. The suffixed id the caller holds
    stays on the wire, so the routing opt-in is preserved â€” the same rule
    :func:`hermes_cli.models.validate_requested_model` applies. Sharing the
    base's cache key is intentional: the window is identical, so a variant and
    its base must never disagree.

    Narrow by design: only applied when the request actually routes through
    OpenRouter, so a local ``model:tag`` that happens to end in one of these
    words is untouched.
    r   r2  zIResolving context length for OpenRouter routing variant %r via base id %r)rN   r>   r   rC  r   rk   rl   )rD   r    rB  Úis_openrouterÚbases        r   Ú!_strip_openrouter_routing_variantrG  þ  s„   € ñ, ØˆØ’^ ×*Ñ*Ó,×2Ñ2Ó4¸ÑDò ÜˆX‹ÒMÔ3°HÓ=ÀÑMð ñ ØˆÜ" 5Ó)€DØ€|ØˆÜ
‡L�LØSØˆtôð €Kr   c                 ó   — t        | «      d uS r9   )rC  r  s    r   Ú_is_known_provider_base_urlrI  %  s   € Ü# HÓ-°TÐ9Ð9r   c                 óŒ   — t        | «      }dD ]3  }|j                  |«      sŒ|dt        |«        j                  d«      c S  |S )z7LM Studio server root for native ``/api/v1`` endpoints.)z/api/v1z/apiú/v1Nrú   )r]   ÚendswithÚlenr  )r    ÚrootrR   s      r   Ú_lmstudio_server_rootrO  )  sL   € ä˜xÓ(€DØ,ò 4ˆØ�=‰=˜Õ Ø˜œ3˜v›;˜,Ð'×.Ñ.¨sÓ3Ò3ð4ð €Kr   c                 óf   — t        | j                  d«      «      }|j                  d«      r|dd S |S )zFProbe root for a local server: IPv4-resolved, ``/v1`` suffix stripped.rú   rK  Néýÿÿÿ)Ú_localhost_to_ipv4r  rL  )r    Ú
server_urls     r   Ú_server_rootrT  2  s3   € ä# H§O¡O°CÓ$8Ó9€JØ(×1Ñ1°%Ô8ˆ:�c�rˆ?ÐH¸jÐHr   )rô   z((?:ú|z)[a-z]+)-(\d{1,2})(?=[-:.@]|$)Úmodel_lowerc                 ó�  — | j                  t        «      r–t        j                  d|«      }| j	                  d«      rAt        j                  t        j                  | «      dz   |j                  dd«      d   «      duS t        j                  t        j                  | «      dz   |«      duS | |v xs t        | «      t        |«      v S )	a|  Substring match with version separators normalised on both sides, so a relay slug like
    ``z-ai-glm-5-3`` still hits the ``glm-5.3`` entry instead of the ``glm`` catch-all (#97398).
    Boundary-matched families: a key must be followed by ``-:.@`` or the end, and a key ending in
    ``-`` is the family default for bare names (``org/`` allowed) continuing with a lineup letter.z\1\2r
  z[a-z]rú   rH   rû   Nz(?:[-:.@]|$))rK   Ú_BOUNDARY_MATCHED_KEY_PREFIXESÚ_HYPHENATED_GENERATION_REÚsubrL  ÚrerP   Úescaperÿ   ÚsearchÚ_normalize_model_version)rn   rV  s     r   Ú_catalog_key_matchesr_  ?  s«   € ð
 ‡~�~Ô4Ô5Ü/×3Ñ3°G¸[ÓIˆØ�<‰<˜ÔÜ—8‘8œBŸI™I c›N¨WÑ4°k×6HÑ6HÈÈaÓ6PÐQSÑ6TÓUÐ]aÐaÐaÜ�y‰yœŸ™ 3›¨/Ñ9¸;ÓGÈtÐSÐSØ�+ÐÒgÔ!9¸#Ó!>ÔBZÐ[fÓBgÐ!gÐgr   Útablec                 ór   — t        | j                  «       d„ d¬«      D ]  \  }}t        ||«      sŒ||fc S  y)zÀFirst ``(key, value)`` whose key is a substring of ``model_lower``, longest key first so
    specific entries (``gpt-5.4-mini``) beat their family catch-all (``gpt-5``); ties keep table order.c                 ó   — t        | d   «      S ©Nr   ©rM  )Úxs    r   ú<lambda>z$_longest_key_match.<locals>.<lambda>O  s   € ¼#¸aÀ¹d»)€ r   T)rn   ÚreverseN)Úsortedr�   r_  )r`  rV  rn   rA   s       r   Ú_longest_key_matchri  L  s@   € ô ˜UŸ[™[›]Ñ0CÈTÔRò ‰
ˆˆUÜ  [Õ1Ø˜�:Òðð r   )ÚminimumÚ
gguf_firstrj  c                ój   ‡ — ˆ fd„}ˆ fd„}|r||fn||fD ]  } |«       D ]  }|�||k\  sŒ|c c S  Œ y)a  Context length from an Ollama ``/api/show`` payload. ``parameters.num_ctx`` is the RUNTIME
    window (Modelfile override), ``model_info.*.context_length`` the GGUF training max. Local users
    control num_ctx (prefer it); hosted operators may cap it arbitrarily (``gguf_first``).c               3   óþ   •K  — ‰j                  dd«      j                  d«      D ]E  } | j                  «       j                  «       }d| v sŒ&t        |«      dk\  sŒ5	 t	        |d   «      –— ŒG y # t
        $ r Y ŒTw xY w­w)NÚ
parametersr   ú
Únum_ctxé   rû   )r*   rL   rN   rM  ÚintÚ
ValueError)ÚlineÚpartsrŒ   s     €r   Ú_num_ctxz&_ollama_show_context.<locals>._num_ctxY  sx   øè ø€ Ø—H‘H˜\¨2Ó.×4Ñ4°TÓ:ò 	ˆDØ—J‘J“L×&Ñ&Ó(ˆEØ˜DÒ ¤S¨£Z°1£_ðÜ˜e B™i›.Ó(ñ		øô
 "ò Ùðüs0   ƒAA=ÁA=ÁA.Á+A=Á.	A:Á7A=Á9A:Á:A=c               3   ó°   •K  — ‰j                  di «      j                  «       D ].  \  } }d| v sŒt        |t        t        f«      sŒ"t        |«      –— Œ0 y ­w)NÚ
model_infor  )r*   r�   r+   rr  r’   )rn   rA   rŒ   s     €r   Ú_ggufz#_ollama_show_context.<locals>._ggufa  sM   øè ø€ ØŸ(™( <°Ó4×:Ñ:Ó<ò 	!‰JˆC�Ø 3Ò&¬:°e¼cÄ5¸\Õ+JÜ˜%“jÓ ñ	!ùs   ƒ+A¯AÁANr:   )rŒ   rk  rj  rv  ry  ÚreaderÚctxs   `      r   Ú_ollama_show_contextr|  U  sR   ø€ ôô!ñ )3�E˜8Ñ$¸À5Ð8Iò ˆÙ“8ò 	ˆCØˆ #¨£.Ø”
ñ	ðð r   z/codingz
/coding/v1>   úkimi-k3-cotÚk3rñ   rK  zdeepseek-ai/deepseek-v4-proc                 óò  ‡‡‡— 	 t        t        |«      «      }|j                  }|j                  j                  «       dk7  s4|dvs0|j                  €$|j                  €|j                  s|j                  ry|j                  xs dj                  «       |j                  j                  d«      | j                  «       j                  «       cŠŠŠt        ˆˆˆfd„t        D «       d«      S # t        $ r Y yw xY w)a  Context confirmed for one provider endpoint only (see _ENDPOINT_SCOPED_CONTEXT): Kimi Coding
    serves K3 at 1 Mi only on the canonical ``api.kimi.com/coding`` host (legacy Moonshot keys do
    not); NVIDIA NIM serves deepseek-v4-pro at 262,144 while DeepSeek's native endpoint is 1M.Nra   )Nrb   r   rú   c              3   óL   •K  — | ]  \  }}}}‰|k(  sŒ‰|v sŒ‰|v sŒ|–— Œ y ­wr9   r:   )r?   Úscoped_hostÚpathsr½   r{  r@  Ú	model_keyr.   s        €€€r   rB   z2_endpoint_scoped_context_length.<locals>.<genexpr>€  sG   øè ø€ ò  WÑ8˜ e¨V°SÐX\Ð`kÓXkÐptÐx}Òp}ð  CLð  PVò  CV”ñ  Wùs   ƒ$“$˜$�$)r   r]   re   rs  r[   r>   ÚusernameÚpasswordÚqueryÚfragmentrd   r.   r  rN   ÚnextÚ_ENDPOINT_SCOPED_CONTEXT)rD   r    rf   re   r@  rƒ  r.   s       @@@r   Ú_endpoint_scoped_context_lengthrŠ  s  s  ú€ ðÜÔ-¨hÓ7Ó8ˆØ�{‰{ˆð ‡}�}×ÑÓ Ò'¨4°{Ñ+BÀfÇoÁoÐFaÐek×etÑetð  fAð  EK÷  EQò  EQð  U[÷  Udò  UdØØ#Ÿ_™_Ò2°×9Ñ9Ó;¸V¿[¹[×=OÑ=OÐPSÓ=TÐV[×VaÑVaÓVc×ViÑViÓVkÐ€Dˆ$�	Üõ  WÔ<Tô  Wð  Y]ó  ^ð  ^øô ò Ùðús   … C* Ã*	C6Ã5C6c                 óJ   — |xs dj                  «       j                  «       dv S )zÌProviders whose disk context cache must not short-circuit probing: LM Studio (loaded
    context is transient), Codex OAuth (entitlement-specific window; a persisted fallback would suppress revalidation).r   >   Úlmstudioúopenai-codex)rN   r>   ©r    rB  s     r   Ú_skip_persistent_context_cacher�  ƒ  s&   € ð ŠN˜×!Ñ!Ó#×)Ñ)Ó+Ð/KÐKÐKr   Úcustom_providersc                 óÖ   — | xs dj                  «       j                  «       dk(  ry|syt        j                  t        «      5  ddlm}  |||«      dk(  cddd«       S # 1 sw Y   yxY w)	aT  True when the request travels the Codex Responses wire regardless of host: the native
    ``openai-codex`` provider (also behind a ``HERMES_CODEX_BASE_URL`` / ``model.base_url`` proxy)
    or a custom entry declaring ``api_mode: codex_responses``. The transport, not the hostname,
    decides which window the model actually gets (#116191).r   r�  TFr   )Úget_custom_provider_api_modeÚcodex_responsesN)rN   r>   Ú
contextlibÚsuppressr0   r)   r’  )rB  r    r�  r’  s       r   Ú_is_codex_router–  ‰  sk   € ð
 	Š�B×ÑÓ×%Ñ%Ó'¨>Ò9ØÙØÜ	×	Ñ	œYÓ	'ñ ]ÝBÙ+¨HÐ6FÓGÐK\Ñ\÷]÷ ]ñ ]ð ús   ÁAÁA(r{  c                 ó8   — t        ||«      st        | ||«       yy)z?Persist ``ctx`` unless the provider opts out of the disk cache.N)r�  Úsave_context_length)rD   r    r{  rB  s       r   Ú_save_unless_skippedr™  ˜  s   € ä)¨(°HÔ=Ü˜E 8¨SÕ1ð >r   Úlengthc                 ó2   — |t         k\  rt        | ||«       yy)zºPersist a probed local window only at/above MINIMUM_CONTEXT_LENGTH: sub-minimum windows are
    still returned so agent_init can reject them, but must not be blessed into the disk cache.N)ÚMINIMUM_CONTEXT_LENGTHr˜  )rD   r    rš  s      r   Ú!_maybe_cache_local_context_lengthr�  ž  s   € ð Ô'Ò'Ü˜E 8¨VÕ4ð (r   c                 ód   — t        | ||¬«      }|r|dkD  syt        ||«      st        | ||«       |S )z\Live local probe; persists a positive result unless the provider opts out of the disk cache.©r   r   N)Ú_query_local_context_lengthr�  r�  )rD   r    r   rB  Ú	local_ctxs        r   Ú_probe_local_context_lengthr¢  ¥  s8   € ä+¨E°8ÀWÔM€IÙ˜) aš-ØÜ)¨(°HÔ=Ü)¨%°¸9ÔEØÐr   Úcachedc                 ó  — t        | ||¬«      }|r
|dkD  r||k7  s|S |t        k  r"t        j                  d| ||d›t        d›«       nt        j                  d| ||d›|d›«       t	        | |«       |t        k\  rt        | ||«       |S )zü*cached* unless a live local probe reports a different limit (operators restart
    vLLM/Ollama with a new --max-model-len / num_ctx under the same id). A failed
    probe keeps the disk entry; sub-minimum live windows invalidate but are not persisted.rŸ  r   uk   Live local probe for %s@%s reports %s (< minimum %s); invalidating stale cache â€” agent init should rejectr™   z@Reconciling stale local cache entry %s@%s: %s -> %s (live probe))r   rœ  rk   ÚinfoÚ!_invalidate_cached_context_lengthr�  )rD   r    r£  r   Úlive_ctxs        r   Ú&_reconcile_local_cached_context_lengthr¨  ¯  sÓ   € ô +¨5°(ÀGÔL€HÙ˜ Aš¨(°fÒ*<ØˆØÔ(Ò(Ü�‰ð  Bð  DIð  KSð  X`ð  abð  Wcô  ið  @Að  hBõ  	Dä�‰ÐVÐX]Ð_gÐlrÐstÐkuð  |Dð  EFð  {Gô  	IÜ% e¨XÔ6ØÔ)Ò)Ü)¨%°¸8ÔDØ€Or   c                 óÒ  — 	 t        | «      }|�|j                  xs dnd}|€y|t        v s0|j	                  t
        «      s|j	                  d«      s
|r	d|vrd|vry	 t        j                  |«      }|j                  s:|j                  s.|j                  s"t        |t        j                  «      r	|t        v ry|j                  d«      }t!        |«      dk7  ry	 t#        |d	   «      t#        |d
   «      }}|dk(  xs> |dk(  xr d|cxk  xr dk  nc xs% |dk(  xr |dk(  xs |dk(  xr d|cxk  xr dk  S c S # t        $ r Y yw xY w# t        $ r Y Œœw xY w# t        $ r Y yw xY w)zÆTrue for loopback, container-internal DNS, unqualified hosts, RFC-1918,
    link-local and Tailscale CGNAT (so a trusted Ollama box over Tailscale gets
    the same timeout auto-bumps as localhost).Nr   Fz.localú.rF   Té   r   rH   é
   é¬   é   é   éÀ   é¨   éd   é@   é   )r_   rd   r0   Ú_LOCAL_HOSTSrL  Ú_CONTAINER_LOCAL_SUFFIXESÚ	ipaddressÚ
ip_addressÚ
is_privateÚis_loopbackÚis_link_localr+   ÚIPv4AddressÚ_TAILSCALE_CGNATrs  rL   rM  rr  )r    rf   r@  Úaddrru  ÚfirstÚseconds          r   Úis_local_endpointrÁ  À  sÀ  € ðÜ  Ó*ˆØ(.Ð(:ˆv�‰Ò$¡"Àˆð €|Øð Œ|Ñ˜tŸ}™}Ô-FÔGÈ4Ï=É=ÐYaÔKbÑgkÐpsÐ{Ñpð  EHð  PTñ  ETØðÜ×#Ñ# DÓ)ˆØ�?Š?˜d×.Ò.°$×2DÒ2DÌÐTXÔZc×ZoÑZoÔIpÐuyô  ~Nñ  vNØð
 �J‰J�s‹O€EÜ
ˆ5ƒz�Q‚ØðÜ˜E !™H›¤s¨5°©8£}ˆvˆð �B‰;ò  N˜5 C™<Ò>¨B°&Ö,>¸BÔ,>ò  NÀEÈSÁLÒDbÐU[Ð_bÑUbò  NÐhmÐqtÑhtò  iMÐy{ð  @Fö  zMð  JMñ  zMð  Nñ  zMð  Nøô1 ò Ùðûô ò Ùðûô ò Ùðús6   ‚D< ÁAE ÃE Ä<	EÅEÅ	EÅEÅ	E&Å%E&Úurlc                 ó\   — | rt        | t        «      s| S t        j                  dd| d¬«      S )zÉ``localhost`` HOST -> ``127.0.0.1`` (Windows dual-stack resolves ::1 first and pays a ~2s IPv6
    connect timeout on IPv4-only servers). Scheme-anchored so ``?upstream=http://localhost`` is untouched.z^(https?://)localhost(?=[:/]|$)z\g<1>127.0.0.1rH   )Úcount)r+   r,   r[  rZ  )rÂ  s    r   rR  rR  â  s-   € ñ ”j ¤cÔ*Øˆ
Ü�6‰6Ð4Ð6GÈÐTUÔVÐVr   c                 óÈ  — ddl }t        t        | «      «      }t        |«      dvryt	        |«      }t        |«      }t        j                  |«      }|�1t        j                  «       |d   z
  |d   �t        nt        k  r|d   S t        |«      ryt        d|«      }t        |t        «      r|t        j                  «       ft        |<   |S d|› d�fd„ fd	|› d
�fd„ fd|› d�|› d�fd„ fd|› d�fd„ ff}d}		 |j!                  dt#        |«      ¬«      5 }
|D ]K  \  }}}	 |D ]$  }|
j                  |«      }|j$                  dk(  sŒ$ n j$                  dk(  r ||«      r|}	 nŒM ddd«       |	t        j                  «       ft        |<   |	�t-        d||	«       |	S # t&        $ r!}t)        |«      rt+        |«       ‚ Y d}~Œ©d}~ww xY w# 1 sw Y   ŒdxY w# t&        $ r Y Œrw xY w)zWProbe known endpoints: "ollama", "lm-studio", "vllm", "llamacpp", or None (TTL-cached).r   N)Nr<  rH   Úserver_typeú	lm-studioú/api/v1/modelsc                  ó   — y)NTr:   ©rƒ   s    r   rf  z*detect_local_server_type.<locals>.<lambda>  s   � r   Úollamaz	/api/tagsc                 ó&   — d| j                  «       v S )Nr½   ©rˆ   rÊ  s    r   rf  z*detect_local_server_type.<locals>.<lambda>  s   € ¸(ÀaÇfÁfÃhÐ:N€ r   Úllamacppú	/v1/propsú/propsc                 ó   — d| j                   v S )NÚdefault_generation_settings)ÚtextrÊ  s    r   rf  z*detect_local_server_type.<locals>.<lambda>  s   € ÐRoÐst×syÑsyÐRy€ r   Úvllmz/versionc                 ó&   — d| j                  «       v S )NÚversionrÍ  rÊ  s    r   rf  z*detect_local_server_type.<locals>.<lambda>  s   € °yÀAÇFÁFÃHÐ7L€ r   g       @©ÚtimeoutÚheaderséÈ   )ry   rR  r]   rC  rT  rO  rY   r*   ri   rj   Ú_ENDPOINT_PROBE_TTL_SECONDSÚ#_ENDPOINT_PROBE_FAILURE_TTL_SECONDSrr   r«   r+   r,   ÚClientr'  Ústatus_coder0   ru   ro   r­   )r    r   ry   r^   rS  Úlmstudio_urlr£  Údisk_hitÚ	waterfallÚresultÚclientr   ÚurlsÚcheckrÂ  rƒ   rs   s                    r   Údetect_local_server_typeræ  ê  s6  € ãä#Ô$7¸Ó$AÓB€Jô
   
Ó+Ð3IÑIØÜ˜jÓ)€JÜ(¨Ó4€LÜ'×+Ñ+¨JÓ7€FØÐœtŸ~™~Ó/°&¸±)Ñ;Ð_eÐfgÑ_hÐ_tÕ@[ô  {^ò  _Ø�a‰yÐô ˜JÔ'ØÜ$ ]°JÓ?€HÜ�(œCÔ Ø2:¼D¿N¹NÓ<LÐ1MÔ" :Ñ.Øˆð 
˜,˜ ~Ð6Ð8¹.ÐIØ	�z�l )Ð,Ð.Ñ0NÐOØ	˜˜ IÐ.°:°,¸fÐ0EÐFÑHyÐzØ	�Z�L Ð)Ð+Ñ-LÐMð	€Ið !€FðØ�\‰\ #¬}¸WÓ/Eˆ\ÓFð 	È&Ø%.ò Ñ!��d˜EðØ#ò "˜Ø"ŸJ™J s›O˜ØŸ=™=¨CÓ/Ù!ð"ð —}‘}¨Ò+±°a´Ø!%˜Ùøð÷	ð$ /5´d·n±nÓ6FÐ-GÔ˜zÑ*ØÐÜ˜m¨Z¸Ô@Ø€Møô !ò ä*¨3Ô/Ü1°*Ô=Øô 0ûðú÷	ð 	ûô ò ÙðúsZ   Ã9G Ä
G	Ä %FÅFÅ"G	Å&G Æ	GÆ%GÆ<G	ÇGÇG	Ç	GÇG Ç	G!Ç G!c              #   óä   K  — t        | t        «      r-| –— | j                  «       D ]  }t        |«      E d {  –—†  Œ y t        | t        «      r| D ]  }t        |«      E d {  –—†  Œ y y 7 Œ37 Œ
­wr9   )r+   rŠ   ÚvaluesÚ_iter_nested_dictsÚlist)rA   ÚnestedÚitems      r   ré  ré  '  so   è ø€ Ü�%œÔØŠØ—l‘l“nò 	2ˆFÜ)¨&Ó1×1Ñ1ñ	2ä	�Eœ4Ô	 Øò 	0ˆDÜ)¨$Ó/×/Ñ/ñ	0ð 
!ð 2øð 0ús!   ‚6A0¸A,¹*A0Á#A.Á$	A0Á.A0Úmaximumc                 óæ   — t        | t        «      ry 	 t        t        | t        «      r | j	                  «       j                  dd«      n| «      }||cxk  r|k  r|S  d S # t        t        f$ r Y y w xY w)Nr™   r   )r+   r   rr  r,   rN   r  Ú	TypeErrorrs  )rA   rj  rí  râ  s       r   Ú_coerce_reasonable_intrð  1  sr   € Ü�%œÔØðÜ´zÀ%ÌÔ7M�U—[‘[“]×*Ñ*¨3°Ô3ÐSXÓYˆð  Ô1¨'Ò1ˆ6Ð;Ð1°tÐ;øô ”zÐ"ò Ùðús   “;A ÁA0Á/A0ÚpayloadÚkeys.c                 óö   — |D �ch c]  }|j                  «       ’Œ }}t        | «      D ]I  }|j                  «       D ]4  \  }}t        |«      j                  «       |v sŒ"t	        |«      }|€Œ0|c c S  ŒK y c c}w r9   )r>   ré  r�   r,   rð  )rñ  rò  rn   ÚkeysetÚmappingrA   Úcoerceds          r   Ú_extract_first_intr÷  ;  sz   € Ø%)Ö*˜cˆc�i‰i�kÐ*€FÐ*Ü% gÓ.ò #ˆØ!Ÿ-™-›/ò 	#‰JˆC�Ü�3‹x�~‰~Ó 6Ò)Ü0°Ó7�ØÑ&Ø"”Nñ		#ð#ð ùò +s   …A6c                 ó`   ‡ — t        d„ t        t        ˆ fd„t        D «       «      D «       d«      S )zÐTop-level-only context WINDOW read (no nested walk, so an unrelated nested section can't leak
    a same-named key). ``max_tokens`` is NOT a window key: on OpenAI-compatible passthroughs it is the max OUTPUT.c              3   ó&   K  — | ]	  }|€Œ|–— Œ y ­wr9   r:   )r?   Úcs     r   rB   z/_extract_flat_context_length.<locals>.<genexpr>I  s   è ø€ Òy�qÐklÑkx”Ñyùó   ‚Šc              3   ó@   •K  — | ]  }‰j                  |«      –— Œ y ­wr9   ©r*   ©r?   rŸ   rñ  s     €r   rB   z/_extract_flat_context_length.<locals>.<genexpr>I  s   øè ø€ Ò8fÈA¸¿¹ÀQ¿Ñ8fùrþ   N)rˆ  Úmaprð  Ú_CONTEXT_LENGTH_KEYS)rñ  s   `r   Ú_extract_flat_context_lengthr  F  s.   ø€ ô ÑyœCÔ 6Ó8fÔQeÔ8fÓgÔyÐ{ó  Að  Ar   c                 óÆ   — t        | t        «      syt        | «      }|�|S | j                  d«      }t        |t        t
        f«      rt	        |«      dkD  rt	        |«      S dS )z¹Context window from a ``/v1/models`` object: window keys first, ``max_tokens`` last (Anthropic
    payloads carry ``max_input_tokens`` = 1M window AND ``max_tokens`` = 128k OUTPUT cap).Nr  r   )r+   rŠ   r  r*   rr  r’   )rñ  r{  Úraws      r   Ú"_context_length_from_model_payloadr  L  sY   € ô �gœtÔ$ØÜ
& wÓ
/€CØ
€Øˆ
Ø
�+‰+�lÓ
#€CÜ! #¬¬U |Ô4¼¸S»ÀAºŒ3ˆs‹8ÐOÈ4ÐOr   rH   iè  )Ú	per_tokenÚper_1k_tokensÚper_thousand_tokensÚper_1m_tokensÚper_million_tokensgü©ñÒMbP?)ÚpromptÚ
completionÚ
cache_readÚcache_writeÚpricingÚunitc                 óÔ  — i }t         D ]  }	 t        | |   «      ||<   Œ t
        j                  t        |xs d«      j                  «       j                  «       «      }|€$t        d„ |j                  «       D «       «      rdnd}|dk7  r?| j                  |j                  «       D ��ci c]  \  }}|t        ||z  «      “Œ c}}«       | S # t        t        t        f$ r Y Œ×w xY wc c}}w )z·Rescale the generic path's token rates to per-token strings (the contract usage_pricing
    multiplies by 1e6), the way the Novita/DeepInfra branches already do for their known units.r   c              3   ó.   K  — | ]  }|t         k\  –— Œ y ­wr9   )Ú_PER_MILLION_QUOTE_MIN©r?   r    s     r   rB   z)_normalize_token_rates.<locals>.<genexpr>m  s   è ø€ Ò"WÀ1 1Ô(>Õ#>Ñ"Wùs   ‚rÎ   rH   )Ú_TOKEN_RATE_FIELDSr’   ÚKeyErrorrï  rs  Ú_PRICING_UNIT_DIVISORSr*   r,   rN   r>   r  rè  Úupdater�   )r  r  Úratesrn   ÚdivisorrA   s         r   Ú_normalize_token_ratesr  b  sÖ   € ð !€EÜ!ò ˆð	Ü˜w s™|Ó,ˆE�#ŠJðô
 %×(Ñ(¬¨TªZ°R«×)>Ñ)>Ó)@×)FÑ)FÓ)HÓI€GØ€Ü"Ñ"WÈÏÉËÔ"WÔW‘)Ð]^ˆØ�!‚|Ø�‰ÀEÇKÁKÃM×R±j°c¸5˜œS ¨¡Ó1Ñ1ÓRÔSØ€Nøô œ)¤ZÐ0ò 	Ùð	üó Ss   �C
Â'C$
Ã
C!Ã C!c                 ó2  ‡ ‡— dt         t        t        f   dt         t        t        f   dt         t        t        f   fd„}dddœ}t        ˆ fd„|j	                  «       D «       «      r |‰ |d	„ «      S ‰ j                  d
«      }t        |t        «      r|j                  d«      nd Šddddœ}t        ‰t        «      r-t        ˆfd„|j	                  «       D «       «      r |‰|d„ «      S ddddddœ}t        ‰ «      D ]’  }|j                  «       D ��ci c]  \  }}t        |«      j                  «       |“Œ! }	}}i }
|j                  «       D ]"  \  }}|D ]  }||	v sŒ|	|   dvsŒ|	|   |
|<    Œ" Œ$ |
sŒwt        |
|	j                  d«      «      c S  i S c c}}w )NÚsourceÚfieldsr!   c                 ó°   — |j                  «       D ��ci c]5  \  }}| j                  |«      €Œ|t         |t        | |   «      «      «      “Œ7 c}}S c c}}w r9   )r�   r*   r,   r’   )r  r  ÚscaleÚtargetrn   s        r   Ú
_per_tokenz$_extract_pricing.<locals>._per_tokent  sJ   € àJPÏ,É,Ë.×x¹;¸6À3Ð\b×\fÑ\fÐgjÓ\kÑ\w�œ™E¤%¨¨s©Ó"4Ó5Ó6Ñ6ÓxÐxùÓxs
   ”A® AÚinput_token_price_per_mÚoutput_token_price_per_m)r
  r  c              3   óD   •K  — | ]  }‰j                  |«      d u–— Œ y ­wr9   rý  rþ  s     €r   rB   z#_extract_pricing.<locals>.<genexpr>x  s   øè ø€ Ò
F¨!ˆ7�;‰;�q‹> Ô%Ñ
Fùs   ƒ c                 ó   — | dz  dz  S )Ni'  rÎ   r:   ©r    s    r   rf  z"_extract_pricing.<locals>.<lambda>y  s   € ¸AÀ¹JÈÑ<R€ r   Úmetadatar  Úinput_tokensÚoutput_tokensÚcache_read_tokens)r
  r  r  c              3   ó&   •K  — | ]  }|‰v –— Œ
 y ­wr9   r:   )r?   rŸ   Údeepinfra_pricings     €r   rB   z#_extract_pricing.<locals>.<genexpr>~  s   øè ø€ Ò2mÈa°1Ð8IÔ3IÑ2mùó   ƒc                 ó   — | dz  S )NrÎ   r:   r&  s    r   rf  z"_extract_pricing.<locals>.<lambda>  s
   € ÈÈYÉ€ r   )r
  ÚinputÚinput_cost_per_tokenÚprompt_token_cost)r  ÚoutputÚoutput_cost_per_tokenÚcompletion_token_cost)ÚrequestÚrequest_cost)r  Úcached_promptÚinput_cache_readÚcache_read_cost_per_token)r  Úcache_creationÚinput_cache_writeÚcache_write_cost_per_token)r
  r  r5  r  r  >   Nr   r  )r   r,   r   r  rè  r*   r+   rŠ   ré  r�   r>   r  )rñ  r!  Únovita_fieldsr'  Údeepinfra_fieldsÚ	alias_maprõ  rn   rA   r^   r  r   r=   Úaliasr,  s   `             @r   Ú_extract_pricingrA  s  s±  ù€ ðyœ4¤¤S ™>ð y´4¼¼S¸±>ð yÌTÔRUÔWZÐRZÉ^ó yð  9ÐHbÑc€MÜ
Ó
F¨}×/CÑ/CÓ/EÔ
FÔFÙ˜' =Ñ2RÓSÐSà�{‰{˜:Ó&€HÜ3=¸hÌÔ3M˜Ÿ™ YÔ/ÐSWÐØ"0ÀÐ_rÑsÐÜÐ#¤TÔ*¬sÓ2mÐSc×SjÑSjÓSlÔ2mÔ/mÙÐ+Ð-=Ñ?VÓWÐWàRØ`Ø.ØfØkñ€Iô & gÓ.ò 	KˆØ@GÇÁÃ×P±*°#°u”c˜#“h—n‘nÓ&¨Ñ-ÐPˆ
ÑPØ"$ˆØ(Ÿ™Ó0ò 	‰OˆF�GØ ò �Ø˜JÒ&¨:°eÑ+<ÀJÒ+NØ&0°Ñ&7�G˜F‘OÙñð	ò
 Ü)¨'°:·>±>À&Ó3IÓJÒJð	Kð €Iùó Qs   Ä$FÚmodel_idr“   c                 ób   — || |<   d|v r&| j                  |j                  dd«      d   |«       y y ©Nrú   rH   )Ú
setdefaultrL   )r~   rB  r“   s      r   Ú_add_model_aliasesrF  ”  s7   € Ø€Eˆ(�OØ
ˆh�Ø×Ñ˜Ÿ™¨¨QÓ/°Ñ2°EÕ:ð r   Úforce_refreshc                 ó�  — | snt         r(t        j                  «       t        z
  t        k  rt         S t	        «       }|�4|t        k  r+t        «       }|r|a t        j                  «       |z
  at         S 	 t        «        t        j                  t        dt        «       ¬«      }|j                  «        i }|j                  «       j                  dg «      D ]�  }|j                  dd«      }|j                  dd«      |j                  d	i «      j                  d
d«      |j                  d|«      |j                  di «      dœ}|j                  dd«      }|r	||k7  r||fn|fD ]  }	t        ||	|«       Œ ŒŸ |a t        j                  «       at        |«       t        j!                  dt#        |«      «       |S # t$        $ rˆ}
t        j'                  d|
«       t         rt         cY d}
~
S t        «       }|rI|a t	        «       }|�t)        |t        «      nt        dz
  }t        j                  «       |z
  at         cY d}
~
S i cY d}
~
S d}
~
ww xY w)z9Fetch model metadata from OpenRouter (cached for 1 hour).N©é   r¬  )rØ  ÚverifyrŒ   Úidr   r  rÃ   Útop_providerr  é   r   r  )r  r  r   r  Úcanonical_slugz.Fetched metadata for %s models from OpenRouterz2Failed to fetch model metadata from OpenRouter: %srH   )rU   ri   rV   Ú_MODEL_CACHE_TTLr´   r¶   r   r   r*   r   r6   Úraise_for_statusrˆ   rF  r¸   rk   rl   rM  r0   rÉ   Úmin)rG  Údisk_ageÚ
disk_cacheÚresponser~   rD   rB  r“   Ú	canonicalr@  r¡   Ústale_bys               r   Úfetch_model_metadatarX  š  s  € ñ Ý ¤d§i¡i£kÔ4NÑ&NÔRbÒ%bÜ(Ð(Ü9Ó;ˆØÐ HÔ/?Ò$?Ü8Ó:ˆJÙØ(2Ð%Ü-1¯Y©Y«[¸8Ñ-CÐ*Ü,Ð,ð!ÜÔô —<‘<Ô 5¸wÔOgÓOiÔjˆØ×!Ñ!Ô#ØˆØ—]‘]“_×(Ñ(¨°Ó4ò 		8ˆEØ—y‘y  rÓ*ˆHà"'§)¡)Ð,<¸fÓ"EØ).¯©°>À2Ó)F×)JÑ)JÐKbÐdhÓ)iØŸ	™	 &¨(Ó3ÀÇ	Á	È)ÐUWÓ@XñˆEð
 Ÿ	™	Ð"2°BÓ7ˆIÙ3<ÀÈhÒAV˜8 YÑ/Ð]eÐ\gò 8�Ü" 5¨%°Õ7ñ8ð		8ð !&ÐÜ%)§Y¡Y£[Ð"Ü'¨Ô.Ü�‰ÐEÄsÈ5ÃzÔRØˆøÜò Ü�‰ÐKÈQÔOÝ Ü(Õ(Ü4Ó6ˆ
ÙØ$.Ð!Ü=Ó?ˆHØ:BÐ:N”s˜8Ô%5Ô6ÔTdÐghÑThˆHÜ)-¯©«°xÑ)?Ð&Ü(Õ(Ø�	ûðús8   Á2EF4 Æ4	IÆ=!I ÇIÇ$AI È3IÈ9I È:IÉ Ir  c                 ó´   — d|fdt        | t        «      fdt        | «      xs dff}d| j                  d|«      i|D ��ci c]  \  }}|€Œ	||“Œ c}}¥S c c}}w )zLCache entry for one ``/models`` item; optional keys are set only when known.r  r  r  Nr   )r÷  Ú_MAX_COMPLETION_KEYSrA  r*   )rD   rB  r  ÚoptionalrŸ   r    s         r   Ú_endpoint_model_entryr\  Ë  sŒ   € à! >Ð2Ð5LÔN`ÐafÔh|ÓN}Ð4~ð  BKô  M]ð  ^có  Mdò  Mlð  hlð  Amð  n€HØ�E—I‘I˜f hÓ/Ð`ÀX×3_¹T¸QÀÐQRÑQ^°A°q±DÓ3_Ð`Ð`ùÓ3_s   ¿
AÁ
Ac                 óü   — | j                  dg «      xs g D ]c  }t        |t        «      r|j                  di «      nd}t        |t        «      r|j                  d«      nd}t        |t        «      sŒ[|dkD  sŒa|c S  y)zNContext of the first loaded LM Studio instance (the runtime value), else None.Úloaded_instancesÚconfigNr  r   )r*   r+   rŠ   rr  )rD   ÚinstÚcfgr{  s       r   Ú_lmstudio_loaded_contextrb  Ñ  sq   € à—	‘	Ð,¨bÓ1Ò7°Rò ˆÜ(2°4¼Ô(>ˆd�h‰h�x Ô$ÀDˆÜ+5°c¼4Ô+@ˆc�g‰gÐ&Ô'ÀdˆÜ�cœ3Õ C¨!£GØŠJð	ð
 r   rÙ  c                 ó  — t        j                  t        | «      j                  d«      dz   |dt	        | «      ¬«      }|j                  «        i }|j                  «       j                  dg «      D ]–  }t        |t        «      r$|j                  d«      xs |j                  d«      nd}|sŒ<t        ||t        |«      «      }t        |||«       |j                  d«      }t        |t        «      sŒ�|sŒ„||k7  sŒŠt        |||«       Œ˜ |S )	uU   LM Studio ``/api/v1/models`` â†’ cache; context comes from the first loaded instance.rú   rÈ  rI  ©rÙ  rØ  rK  r½   rn   rL  N)r   r*   rO  r  r6   rQ  rˆ   r+   rŠ   r\  rb  rF  r,   )r^   rÙ  rU  r~   rD   rB  r“   Úalt_ids           r   Ú_lmstudio_native_modelsrf  Û  sù   € ä�|‰|Ô1°*Ó=×DÑDÀSÓIÐL\Ñ\ÐfmÐw~ô  H`ð  akó  Hlô  m€HØ×ÑÔØ')€EØ—‘“×$Ñ$ X¨rÓ2ò 5ˆÜ<FÀuÌdÔ<S�E—I‘I˜eÓ$Ò7¨¯	©	°$¬ÐY]ˆÙØÜ% e¨XÔ7OÐPUÓ7VÓWˆÜ˜5 (¨EÔ2Ø—‘˜4“ˆÜ�fœcÕ"¢v°&¸HÓ2DÜ˜u f¨eÕ4ð5ð €Lr   Úrequest_candidatec                 óî  ‡‡‡— |j                  d«      j                  dd«      Šdˆˆˆfd„	}dt        t        t        f   dt        fd„} |«       }|j
                  r;|j                  «       } ||«      |j                  d	d«      }	}|r|	r|	| v r|| |	   d
<   yt        j                  ‰dz   ‰d‰¬«      }
|
j
                  sy|
j                  «       xs i j                  dg «      dd D ]‹  }t        |t        «      r|j                  d«      nd}|r*|| vs&|j                  d«      xs i j                  d«      dvrŒS |d|i«      }|j
                  r ||j                  «       «      nd}|sŒ„|| |   d
<   Œ� y)u"  Overwrite ``context_length`` with llama.cpp's allocated ``n_ctx`` from /props (``/v1/props``, then
    ``/props`` for older builds). In router mode the bare endpoint 400s, so each LOADED child is read
    via ``/props?model=``; unloaded children are skipped â€” probing could autoload them.rú   rK  r   Nc                 ó”   •— t        j                  ‰dz   | ‰d‰¬«      }|j                  st        j                  ‰dz   | ‰d‰¬«      }|S )NrÏ  rJ  )ÚparamsrÙ  rØ  rK  rÐ  )r   r*   Úok)rj  ÚresprF  rÙ  rK  s     €€€r   Ú_propsz%_apply_llamacpp_props.<locals>._propsñ  sH   ø€ Ü�|‰|˜D ;Ñ.°vÀwÐXYÐbhÔiˆØ�wŠwÜ—<‘<  x¡¸ÈÐYZÐciÔjˆDØˆr   Úpropsr!   c                 óJ   — | j                  d«      xs i j                  d«      S )NrÒ  r  rý  )rn  s    r   Ú_n_ctxz%_apply_llamacpp_props.<locals>._n_ctxö  s"   € Ø—	‘	Ð7Ó8Ò>¸B×CÑCÀGÓLÐLr   Úmodel_aliasr  ú/modelsrJ  rd  rŒ   r®  rL  ÚstatusrA   )ÚloadedÚreadyrD   r9   )r  r  r   r,   r   rk  rˆ   r*   r   r+   rŠ   )r~   rg  rÙ  rK  rm  rp  Ú
props_resprn  r  rq  ÚnativeÚchildÚchild_idÚprÚ	child_ctxrF  s     ``           @r   Ú_apply_llamacpp_propsr|  ì  sg  ú€ ð ×#Ñ# CÓ(×0Ñ0°¸Ó;€D÷ð
M”dœ3¤˜8‘nð M¬ó Má“€JØ‡}‚}Ø—‘Ó!ˆÙ# E›]¨E¯I©I°mÀRÓ,Hˆ{ˆÙ‘[ [°EÑ%9Ø38ˆE�+ÑÐ/Ñ0ØÜ�\‰\˜$ Ñ*°GÀQÈvÔV€FØ�9Š9ØØ—+‘+“-Ò% 2×*Ñ*¨6°2Ó6°s¸Ð;ò :ˆÜ&0°¼Ô&=�5—9‘9˜T”?À4ˆÙ˜8¨5Ñ0°U·Y±Y¸xÓ5HÒ5NÈB×4SÑ4SÐT[Ó4\ÐdwÑ4wØÙ�W˜hÐ'Ó(ˆØ)+¯ª‘F˜2Ÿ7™7›9Ô%°Dˆ	ÚØ09ˆE�(‰OÐ,Ò-ñ:r   c                 óP   — ddl m} | t        |t        «      r ||«      xs dfS dfS )Nr   )Úfingerprint_secret_valuer   )Úagent.credential_persistencer~  r+   r,   )r^   r   r~  s      r   Ú_endpoint_memo_keyr€    s.   € ÝEàÄJÈwÔX[ÔD\Ñ0°Ó9Ò?¸RÐdÐdÐbdÐdÐdr   Úmemo_keyc                 óN   — |t         | <   t        j                  «       t        | <   |S r9   )rW   ri   rX   )r�  r~   s     r   Ú_remember_endpoint_modelsrƒ    s#   € Ø/4Ô" 8Ñ,Ü48·I±I³KÔ'¨Ñ1Ø€Lr   c                 óÐ   — i }| j                  dg «      D ]N  }t        |t        «      r|j                  d«      nd }|sŒ)t        ||t	        ||t        |t        «      «      «       ŒP |S )NrŒ   rL  )r*   r+   rŠ   rF  r\  r÷  r   )rñ  r~   rD   rB  s       r   Ú_parse_models_payloadr…    ss   € Ø')€EØ—‘˜V RÓ(ò IˆÜ&0°¼Ô&=�5—9‘9˜T”?À4ˆÚÜ˜u hÔ0EÀeÈXÔWiÐjoô  rFó  XGó  1Hõ  IðIð €Lr   c                 ó8  — t        | «      }|rt        |d«      ri S t        «        t        |«      }t	        ||«      }|sht
        j                  |«      }|�4t        j                  «       t        j                  |d«      z
  t        k  r|S |st        |«      nd}|�t        ||«      S t        |«      ri S |j                  d«      r|dd j                  d«      n|dz   }|g||k7  r|gng z   }	t        |«      }
t!        |«      }d}|r(	 t#        ||¬«      dk(  rt        |t%        ||
«      «      S 	 |	D �]?  }t        |«      r �n1t+        |«      }|j                  d«      d	z   }d}	 t-        j                  ||
d
|d¬«      }|j.                  dv r6t0        j3                  d|j.                  |«       	 |�|j5                  «         n±|j7                  «        |j9                  «       }t;        |«      }t=        d„ |j                  dg «      D «       «      r0t?        j@                  t&        «      5  tC        |||
|«       ddd«       |r|stE        ||«       t        ||«      |�|j5                  «        c S c S  |rt0        j3                  d||«       t        |i «      S # t&        $ r}|}t)        ||«       Y d}~�Œ‡d}~ww xY w# 1 sw Y   Œ‡xY w# t&        $ r}|}t)        ||«       Y d}~nd}~ww xY w	 |€�ŒÂ|j5                  «        �ŒÔ# |�|j5                  «        w w xY w)zTModel metadata from an OpenAI-compatible ``/models`` endpoint (cached per base URL).r)  Nr   rK  rQ  rú   rŸ  rÇ  rr  rI  T)rÙ  rØ  rK  Ústream)i‘  i“  zIModel metadata probe received HTTP %s from %s; stopping candidate probingc              3   óf   K  — | ])  }t        |t        «      sŒ|j                  d «      dk(  –— Œ+ y­w)Úowned_byrÎ  N©r+   rŠ   r*   )r?   Úms     r   rB   z0fetch_endpoint_model_metadata.<locals>.<genexpr>O  s*   è ø€ Òk°qÔWaÐbcÔeiÕWj�1—5‘5˜Ó$¨
Õ2Ñkùs   ‚1˜1rŒ   z1Failed to fetch model metadata from %s/models: %s)#r]   r   r   rÁ  r€  rW   r*   ri   rX   r¾   r¿   rƒ  rr   rL  r  r'  r6   ræ  rf  r0   rv   rR  r   rÞ  rk   rl   ÚcloserQ  rˆ   r…  r  r”  r•  r|  rÁ   )r    r   rG  r^   Úlocalr�  r£  ÚmemoÚ	alternateÚ
candidatesrÙ  rK  Ú
last_errorrs   Ú	candidaterg  rÂ  rU  rñ  r~   s                       r   Úfetch_endpoint_model_metadatar“  !  s  € ä$ XÓ.€JÙÔ.¨z¸?ÔKØˆ	ÜÔÜ˜jÓ)€EÜ! *¨gÓ6€HÙÜ/×3Ñ3°HÓ=ˆØÐ¤4§9¡9£;Ô1T×1XÑ1XÐYaÐcdÓ1eÑ#eô  jCò  #CØˆMÙ;@Ô'¨
Ô3ÀdˆØÐÜ,¨X°tÓ<Ð<ä˜JÔ'Øˆ	Ø/9×/BÑ/BÀ5Ô/I�
˜3˜B�×&Ñ& sÔ+ÈzÐ\aÑOa€IØ�°	¸ZÒ0G )¡ÈRÑP€JÜ˜GÓ$€GÜ% jÓ1€FØ&*€JÙð	6Ü'¨
¸GÔDÈÒSÜ0°Ô;RÐS]Ð_fÓ;gÓhÐhð Tð
  ó !ˆ	ä 
Ô+Úä.¨yÓ9ÐØ×&Ñ& sÓ+¨iÑ7ˆØˆð	!Ü—|‘| C°À'ÐRXÐaeÔfˆHØ×#Ñ# zÑ1Ü—‘ÐhÐjr×j~Ñj~ð  ADô  EØð Ð#Ø—‘Ô ùð ×%Ñ%Ô'Ø—m‘m“oˆGÜ)¨'Ó2ˆEÜÑk¸G¿K¹KÈÐPRÓ<SÔkÔkÜ×(Ñ(¬Ó3ñ UÜ)¨%Ð1BÀGÈVÔT÷Uá™UÜ(¨°UÔ;Ü,¨X°uÓ=ð
 Ð#Ø—‘× ò $ð5!ñ8 Ü�‰ÐHÈ*ÐV`ÔaÜ$ X¨rÓ2Ð2øôC ò 	6ØˆJÜ$ S¨*×5Ò5ûð	6ú÷(Uð Uûô
 ò 	6ØˆJÜ$ S¨*×5Ñ5ûð	6úà5àÒ#Ø—‘Ö øð Ð#Ø—‘Õ ð $úsb   Ä%J Å$A	K	ÇA&K	È(J=È7#K	Ê	J:Ê!J5Ê5J:Ê=K	ËK	Ë		K*ËK%Ë LË%K*Ë*LÌLc                 óF  ‡ — t        ||¬«      }|j                  ‰ «      }|s1t        |«      dk(  r#t        t	        |j                  «       «      «      }n'|s%‰ r#t        ˆ fd„|j                  «       D «       d«      }|r|j                  d«      nd}t        |t        «      r|S dS )zDResolve context length from an endpoint's live ``/models`` metadata.rŸ  rH   c              3   ó:   •K  — | ]  \  }}‰|v s|‰v sŒ|–— Œ y ­wr9   r:   )r?   rn   r“   rD   s      €r   rB   z3_resolve_endpoint_context_length.<locals>.<genexpr>g  s%   øè ø€ Òj¡* # uÈUÐVYÉ\Ð]`ÐdiÒ]iœÑjùó   ƒ”Nr  )	r“  r*   rM  rˆ  Úiterrè  r�   r+   rr  )rD   r    r   Úendpoint_metadataÚmatchedr  s   `     r   Ú _resolve_endpoint_context_lengthrš  `  s’   ø€ ä5°hÈÔPÐØ×#Ñ# EÓ*€GÙ”sÐ,Ó-°Ò2Ü”tÐ-×4Ñ4Ó6Ó7Ó8‰Ù™ÜÓjÐ0A×0GÑ0GÓ0IÔjÐlpÓqˆÙ6=�W—[‘[Ð!1Ô2À4€NÜ'¨¼Ô<ˆ>ÐFÀ$ÐFr   c                  ó"   — ddl m}   | «       dz  S )z1Path to the persistent context length cache file.r   r|   zcontext_length_cache.yamlr   r|   s    r   Ú_get_context_cache_pathrœ  l  s   € å0ÙÓÐ:Ñ:Ð:r   c                  óš  — t        «       } | j                  «       si S 	 t        | d¬«      5 }t        j                  |«      }t        |t        «      si cddd«       S dD ]'  }t        |j                  |«      t        «      rŒ#i ||<   Œ) |cddd«       S # 1 sw Y   yxY w# t        $ r"}t        j                  d|«       i cY d}~S d}~ww xY w)zGRead scalar lengths and their provenance from the same atomic document.r„   r…   N)Úcontext_lengthsÚbedrock_confirmed_v1z'Failed to load context length cache: %s)rœ  Úexistsr‡   ÚyamlÚ	safe_loadr+   rŠ   r*   r0   rk   rl   )r.   r‹   rŒ   Úsectionr¡   s        r   Ú_load_context_cache_documentr¤  r  s»   € ä"Ó$€DØ�;‰;Œ=Øˆ	ðÜ�$ Ô)ð 	¨QÜ—>‘> !Ó$ˆDÜ˜d¤DÔ)Ø÷	ñ 	ð Gò '�Ü! $§(¡(¨7Ó"3´TÕ:Ø$&�D˜’Mð'ð ÷	÷ 	ò 	ûô ò Ü�‰Ð>ÀÔBØ�	ûðúsL   žB «'BÁ	B Á$BÂBÂ		B ÂBÂB ÂB Â	C
Â(CÂ?C
ÃC
c                  ó<   — t        «       j                  d«      xs i S )z;Load scalar lengths, preserving the legacy reader contract.rž  )r¤  r*   r:   r   r   Ú_load_context_cacher¦  …  s   € ä'Ó)×-Ñ-Ð.?Ó@ÒFÀBÐFr   Úbedrock_confirmedc                 óB   — d| i}|r||d<   t        t        «       |«       y)z¥Atomic write (a truncating write killed mid-dump leaves a partial file that
    _load_context_cache() swallows as {}, wiping EVERY cached length). Raises on failure.rž  rŸ  N)r   rœ  )r~   r§  Údocuments      r   Ú_write_context_cacherª  Š  s*   € ð " 5Ð)€HÙØ+<ˆÐ'Ñ(ÜÔ-Ó/°Õ:r   c                 ó6   — | › d|xs dj                  d«      › �S )zdCanonical ``model@base_url`` key; trailing slashes stripped so ``/v1`` and ``/v1/`` share one entry.ú@r   rú   )r  )rD   r    s     r   Ú_context_cache_keyr­  “  s#   € àˆW�A�x’~ 2×-Ñ-¨cÓ2Ð3Ð4Ð4r   ©r  r  c                óN  — |dk  rt         j                  d| › d|› �|«       yt        | |«      }t        «       }|j	                  d«      xs i }|j	                  d«      xs i }t        |t        «      r|ni }|j                  «       }|| › d|› �|› d�fD ]  }	|j                  |	d«       Œ |dk(  r|||<   |j	                  |«      |k(  r||k(  ry|||<   	 t        ||«       t         j                  d	||d
›«       y# t        $ r }
t         j                  d|
«       Y d}
~
yd}
~
ww xY w)zqPersist a discovered context length under ``model@base_url`` (same model, different providers, different limits).r   z=Refusing to cache non-positive context length %s -> %s tokensr¬  Nrž  rŸ  rú   úbedrock-confirmed-v1z%Cached context length %s -> %s tokensr™   z'Failed to save context length cache: %s)rk   rÉ   r­  r¤  r*   r+   rŠ   ÚcopyÚpoprª  r¥  r0   rl   )rD   r    rš  r  rn   r©  r~   Ú	confirmedÚold_confirmedr@  r¡   s              r   r˜  r˜  ˜  s=  € ð �‚{Ü�‰ÐVÐ[`ÐZaÐabÐckÐblÐXmÐouÔvØÜ
˜U HÓ
-€CÜ+Ó-€HØ�L‰LÐ*Ó+Ò1¨r€EØ—‘Ð3Ó4Ò:¸€IÜ'¨	´4Ô8‘	¸b€IØ—N‘NÓ$€Mð ˜%˜  ( Ð,°°°Q¨iÐ8ò #ˆØ�‰�e˜TÕ"ð#àÐ'Ò'Øˆ	�#‰Ø‡y�y�ƒ~˜Ò I°Ò$>ØØ€Eˆ#�JðCÜ˜U IÔ.Ü�‰Ð;¸SÀVÈAÀJÕPøÜò CÜ�‰Ð>À×BÑBûðCús   Ã%C; Ã;	D$ÄDÄD$c                 ó^   — t        ||«      rt        | |xs d|d¬«       yt        | ||«       y)zUPersist a provider-confirmed window, distinguishing it from legacy Bedrock fallbacks.ú
bedrock://r°  r®  N)Ú_is_bedrock_contextr˜  )rD   r    rš  rB  s       r   Úsave_provider_context_lengthr¸  ´  s,   € ä˜8 XÔ.Ü˜E 8Ò#;¨|¸VÐLbÖcä˜E 8¨VÕ4r   ©r§  c                ó   ‡	— t        | |«      }t        «       }|j                  d«      xs i Š	t        ‰	t        «      syt        ˆ	fd„|| › d|› �|› d�fD «       d«      }‰	j                  |«      }t        |«      t        ury|rK|j                  d«      }t        |t        «      r|j                  |«      nd}t        |«      t        us||k7  ry|S )zBLook up a previously discovered context length for model+provider.rž  Nc              3   óF   •K  — | ]  }‰j                  |«      €Œ|–— Œ y ­wr9   rý  )r?   rŸ   r~   s     €r   rB   z,get_cached_context_length.<locals>.<genexpr>Ä  s   øè ø€ Òg˜aÈeÏiÉiÐXYËlÑNfœÑgùs   ƒ!š!r¬  rú   rŸ  )r­  r¤  r*   r+   rŠ   rˆ  Útyperr  )
rD   r    r§  rn   r©  Úmatched_keyrš  r³  Úmarkerr~   s
            @r   Úget_cached_context_lengthr¿  ¼  sÇ   ø€ ä
˜U HÓ
-€CÜ+Ó-€HØ�L‰LÐ*Ó+Ò1¨r€EÜ�eœTÔ"ØäÓg C¨E¨7°!°H°:Ð)>À3À%ÀqÀ	Ð#JÔgÐimÓn€KØ�Y‰Y�{Ó#€FÜˆFƒ|œ3ÑØÙØ—L‘LÐ!7Ó8ˆ	Ü/9¸)ÄTÔ/J�—‘˜{Ô+ÐPTˆÜ�‹<œsÑ" f°Ò&6ØØ€Mr   c                 óö  ‡‡— t        | |«      }t        «       }|j                  d«      xs i Š|j                  d«      xs i Št        ‰t        «      r‰ni Št        | «      |xs dj                  d«      }}t        j                  ||fd«       t        j                  d||fd«       ddl	m
} t        t        «      D ]2  }|dd	  |«       |fk(  sŒ|d	   | |fv sŒt        j                  |d«       Œ4 || › d
|› �|› d�h}t        ˆˆfd„|D «       «      sy|D ]&  }	‰j                  |	d«       ‰j                  |	d«       Œ( 	 t        ‰‰«       y# t        $ r!}
t         j#                  d||
«       Y d}
~
yd}
~
ww xY w)zçDrop a stale entry and its probe cooldown using the persisted cache URL.

    Bedrock callers without a runtime endpoint must pass ``bedrock://``, as
    the resolver does; a blank URL addresses the distinct generic cache key.
    rž  rŸ  r   rú   NÚollama_showr   ©Úhermes_home_keyrq  r¬  c              3   ó2   •K  — | ]  }|‰v xs |‰v –— Œ y ­wr9   r:   )r?   rŸ   r~   r³  s     €€r   rB   z4_invalidate_cached_context_length.<locals>.<genexpr>ç  s!   øè ø€ Ò@°ˆq�EˆzÒ+˜Q )˜^Ó+Ñ@ùs   ƒz6Failed to invalidate context length cache entry %s: %s)r­  r¤  r*   r+   rŠ   rT   r  rÌ   r²  r€   rÃ  rê  rÍ   r  rª  r0   rk   rl   )rD   r    rn   r©  ÚbareÚstrippedrÃ  r�  Ú
stale_keysrŸ   r¡   r~   r³  s              @@r   r¦  r¦  Ð  s|  ù€ ô ˜U HÓ
-€CÜ+Ó-€HØ�L‰LÐ*Ó+Ò1¨r€EØ—‘Ð3Ó4Ò:¸€IÜ'¨	´4Ô8‘	¸b€Iä+¨EÓ2°X²^À×4KÑ4KÈCÓ4Pˆ(€DÜ×Ñ  hÐ/°Ô6Ü×Ñ ¨t°XÐ>ÀÔEõ 1ÜÔ5Ó6ò =ˆØ�B�Qˆ<™OÓ-¨xÐ8Ó8¸XÀa¹[ÈUÐTXÈMÒ=YÜ(×,Ñ,¨X°tÕ<ð=ð ˜%˜  ( Ð,°°°Q¨iÐ8€JÜÔ@°ZÔ@Ô@ØØò ˆØ�	‰	�!�TÔØ�‰�a˜ÕððWÜ˜U IÕ.øÜò WÜ�‰ÐMÈsÐTU×VÑVûðWús   ÅE Å	E8ÅE3Å3E8Úcurrent_lengthc                 ó6   ‡ — t        ˆ fd„t        D «       d«      S )z5Next lower probe tier, or None if already at minimum.c              3   ó.   •K  — | ]  }|‰k  sŒ	|–— Œ y ­wr9   r:   )r?   ÚtierrÈ  s     €r   rB   z&get_next_probe_tier.<locals>.<genexpr>ô  s   øè ø€ ÒO˜$¸ÀÓ9N”ÑOùs   ƒ
ŽN)rˆ  ÚCONTEXT_PROBE_TIERS)rÈ  s   `r   Úget_next_probe_tierrÍ  ò  s   ø€ äÓOÔ"5ÔOÐQUÓVÐVr   Ú	error_msgc                 óÖ   ‡— | j                  «       Šd‰v sd‰v sd‰v rd‰vryd}t        dˆfd„|D «       «      D ]-  }t        |j                  d«      «      }d	|cxk  r	d
k  sŒ)|c S  Œ/ y)a  Context limit quoted in a provider error ("maximum context length is 32768 tokens"), if any.

    A message about only an OUTPUT cap ("... model output limit of 16384") never says "context";
    bail out so the generic "limit ... of N" pattern can't cache the output cap as the window.úoutput limitúoutput tokenszoutput tokenÚcontextN)z+max_model_len\s*(?:is\s*)?[:=(]?\s*(\d{4,})z2maximum model length\s*(?:is\s*)?[:=(]?\s*(\d{4,})zY(?:max(?:imum)?|limit)\s*(?:context\s*)?(?:length|size|window)?\s*(?:is|of|:)?\s*(\d{4,})z:context\s*(?:length|size|window)\s*(?:is|of|:)?\s*(\d{4,})z)(\d{4,})\s*(?:token)?\s*(?:context|limit)z">\s*(\d{4,})\s*(?:max|limit|token)z(\d{4,})\s*(?:max(?:imum)?)\bz*supports?\s+(?:only\s+)?up\s+to\s+(\d{4,})c              3   óJ   •K  — | ]  }t        j                  |‰«      –— Œ y ­wr9   )r[  r]  )r?   ÚpatternÚerror_lowers     €r   rB   z1parse_context_limit_from_error.<locals>.<genexpr>  s   øè ø€ ÒWÀ7œrŸy™y¨°+×>ÑWùs   ƒ #rH   é   é€–˜ )r>   Úfilterrr  Úgroup)rÎ  ÚpatternsrP   ÚlimitrÕ  s       @r   Úparse_context_limit_from_errorrÜ  ÷  s�   ø€ ð
 —/‘/Ó#€KØ˜+Ñ%¨¸KÑ)GÈ>Ð]hÑKhÐnwð  @Kñ  oKØð€Hô ˜ÓWÈhÔWÓXò ˆÜ�E—K‘K “NÓ#ˆØ�5Ô&˜JÓ&ØŠLñ 'ðð r   Úcurrent_context_lengthc                 ó.   — t        | «      }|�||k  r|S dS )a  Provider-reported limit LOWER than the current window, else None. Overflow recovery must
    not invent a window: when the provider only says the input is too long, callers keep the
    configured length and compress rather than stepping down guessed probe tiers.N)rÜ  )rÎ  rÝ  Úparsed_limits      r   Ú&get_context_length_from_provider_errorrà    s'   € ô 2°)Ó<€LØ'Ð3¸ÐG]Ò8]ˆ<ÐgÐcgÐgr   z}\((\d+)\s+(?:tokens\s+)?in (?:the messages|your prompt|the prompt)\s*[;,]\s*(\d+)\s+(?:tokens\s+)?(?:in|for) the completion\)rÕ  c                 óÞ   — t         j                  | «      }t        j                  d| «      }|r|syt        |j	                  d«      «      t        |j	                  d«      «      z
  }|dk\  r|S dS )z·window - measured prompt from the OpenAI-style parenthetical split, or None when the wording
    is absent or the prompt alone fills the window (a genuine input overflow -> compress).úmaximum context length is (\d+)NrH   )Ú_COMPLETION_SPLIT_REr]  r[  rr  rÙ  )rÕ  rL   r{  Ú	availables       r   Ú_completion_split_budgetrå  #  sb   € ô !×'Ñ'¨Ó4€EÜ
�)‰)Ð6¸Ó
D€CÙ™ØÜ�C—I‘I˜a“LÓ!¤C¨¯©°A«Ó$7Ñ7€IØ! Qšˆ9Ð0¨DÐ0r   c                 óš  — | j                  «       }t        |t        «      sydD ]T  }t        j                  ||«      }|sŒt        |j                  d«      «      dk\  sŒ:t        |j                  d«      «      c S  t        j                  d|«      }t        j                  d|«      }|rY|rWt        |j                  d«      «      t        |j                  d«      «      z
  t        |j                  d«      «      z
  }|dk\  r|S t        |«      }|�|S t        j                  d|«      }t        j                  d|«      }	|rD|	rBt        |j                  d«      «      t        |	j                  d«      «      dz   d	z  z
  }|dk\  r|S t        |«      }
|
r|
d
   |
d   z
  dk\  r|
d
   |
d   z
  S t        j                  d|«      }|r‹|r‰t        |j                  d«      «      t        |j                  d«      «      z
  }t        j                  d|«      }d|v r3|r1t        |j                  d«      «      }||dz
  k\  rt        d|dz  «      S |dk\  r|S y)zýAvailable OUTPUT tokens from a "max_tokens too large" error, or None. Distinct from "prompt
    too long" (-> compress): here input + requested_output > window, so the fix is a smaller
    max_tokens for this call and context_length must NOT be touched.N)	z?exceeds model(?:\'s)? maximum output tokens\s*\(?\s*(\d+)\s*\)?z\max_tokens\s*:\s*\d+\s*>\s*(\d+)\s*,?\s*which is the maximum allowed number of output tokensz9range of max_tokens should be\s*\[\s*\d+\s*,\s*(\d+)\s*\]zavailable_tokens[:\s]+(\d+)zavailable\s+tokens[:\s]+(\d+)zoutput limit (?:of|is)\s*(\d+)z3supports at most\s+(\d+)\s*(?:completion\s+)?tokensz:(?:max_tokens|max_completion_tokens) is limited to\s*(\d+)z=\s*(\d+)\s*$rH   râ  zK\((\d+)\s+of text input,\s*(\d+)\s+of tool input,\s*(\d+)\s+in the output\)rq  z'maximum context length is (\d+)\s*tokenz!prompt contains (\d+)\s*characteré   r   z2prompt contains (?:at least )?(\d+)\s*input tokenszrequested (\d+)\s*output tokenszat least)
r>   Ú_any_phrase_groupÚ_PARSEABLE_OUTPUT_CAP_SIGNALSr[  r]  rr  rÙ  rå  Ú_sglang_window_and_inputÚmax)rÎ  rÕ  rÔ  rP   Ú_m_ctxÚ_m_partsÚ
_availableÚ_split_availableÚ
_m_ctx_tokÚ_m_charsÚ	_m_sglangÚ_m_vllm_inputÚ_m_requested_outÚ_requested_outs                 r   Ú(parse_available_output_tokens_from_errorrö  .  s4  € ð —/‘/Ó#€KÜ˜[Ô*GÔHØð
ò 'ˆô —	‘	˜' ;Ó/ˆÚ”S˜Ÿ™ Q›Ó(¨AÓ-Ü�u—{‘{ 1“~Ó&Ò&ð!'ô$ �Y‰YÐ9¸;ÓG€FÜ�y‰yÐgÐitÓu€HÙ‘(Ü˜Ÿ™ a›Ó)¬C°·±¸qÓ0AÓ,BÑBÄSÈÏÉÐXYÓIZÓE[Ñ[ˆ
Ø˜Š?ØÐÜ/°Ó<ÐØÐ#ØÐä—‘ÐEÀ{ÓS€JÜ�y‰yÐ=¸{ÓK€HÙ‘hÜ˜×)Ñ)¨!Ó,Ó-´°X·^±^ÀAÓ5FÓ1GÈ!Ñ1KÐPQÑ0QÑQˆ
Ø˜Š?ØÐô )¨Ó5€IÙ�Y˜q‘\ I¨a¡LÑ0°AÒ5Ø˜‰|˜i¨™lÑ*Ð*ô
 —I‘IÐSÐU`Óa€MÙ‘mÜ˜×)Ñ)¨!Ó,Ó-´°M×4GÑ4GÈÓ4JÓ0KÑKˆ
ÜŸ9™9Ð%GÈÓUÐØ˜Ñ$Ñ)9Ü Ð!1×!7Ñ!7¸Ó!:Ó;ˆNØ˜^¨aÑ/Ò/ä˜1˜n°Ñ1Ó2Ð2Ø˜Š?ØÐØr   )©zrange of max_tokens should be)Úavailable_tokens)úavailable tokens©zin the outputúmaximum context length)Ú	requestedrÑ  )z	should be)zless than or equal)zmust be©zexceeds modelzmaximum output tokens©rÐ  )ú'maximum allowed number of output tokens©zmax_tokens is too largezsupports at most©ztokens from the input messagesútokens for the completion©z
limited to)zprompt is too longzprompt too longzinput is too longzinput tokenzprompt lengthzprompt containszreduce the length))r  rø  )r  rù  rú  )rû  rü  rÑ  )rû  zin the completion)rû  zfor the completionr÷  rý  rþ  )r  rÿ  r   r  r  c                 óÎ   — t        j                  d| «      }t        j                  d| «      }|r6|r4t        |j                  d«      «      t        |j                  d«      «      fS dS )z]``(window, input_tokens)`` from SGLang's wording, else None; both figures are explicit there.z'maximum context length of (\d+)\s*tokenz&(\d+)\s*tokens from the input messagesrH   N)r[  r]  rr  rÙ  )rÕ  rì  Ú_m_ins      r   rê  rê  ’  sS   € ä�Y‰YÐAÀ;ÓO€FÜ�I‰IÐ?ÀÓM€EÙ:@ÁUŒC�—‘˜Q“Ó ¤# e§k¡k°!£nÓ"5Ð6ÐTÐPTÐTr   rÓ  Úgroupsc                 ó,   ‡ — t        ˆ fd„|D «       «      S )Nc              3   óF   •K  — | ]  }t        ˆfd „|D «       «      –— Œ y­w)c              3   ó&   •K  — | ]  }|‰v –— Œ
 y ­wr9   r:   )r?   ÚprÓ  s     €r   rB   z._any_phrase_group.<locals>.<genexpr>.<genexpr>š  s   øè ø€ Ò, �1˜”9Ñ,ùr-  N)Úall)r?   rÙ  rÓ  s     €r   rB   z$_any_phrase_group.<locals>.<genexpr>š  s   øè ø€ ÒA°ŒsÓ, eÔ,×,ÑAùs   ƒ!©r  )rÓ  r  s   ` r   rè  rè  ™  s   ø€ ÜÓA¸&ÔAÓAÐAr   c                 óø   ‡— | j                  «       Št        ‰«      �yt        ‰«      }t        ˆfd„dD «       «      xr= t	        ‰t
        «      xr+ t        ˆfd„t        D «       «       xr |xr |d   |d   k\   S )a,  Yes/no sibling of :func:`parse_available_output_tokens_from_error` for unparseable wordings. An
    output-cap 400 misclassified as context overflow death-loops the compressor (same max_tokens, same
    rejection). Signal: talks about max_tokens as a cap/range/limit and NOT about an oversized input.Tc              3   ó&   •K  — | ]  }|‰v –— Œ
 y ­wr9   r:   ©r?   r
  rÕ  s     €r   rB   z&is_output_cap_error.<locals>.<genexpr>ª  s   øè ø€ ò  A ˆA�Ôñ  Aùr-  )r  r  r  r  c              3   ó&   •K  — | ]  }|‰v –— Œ
 y ­wr9   r:   r  s     €r   rB   z&is_output_cap_error.<locals>.<genexpr>¬  s   øè ø€ ÒF¨�A˜Ô$ÑFùr-  rH   r   )r>   rå  rê  r  rè  Ú_OUTPUT_CAP_SIGNALSÚ_INPUT_OVERFLOW_SIGNALS)rÎ  rò  rÕ  s     @r   Úis_output_cap_errorr  �  s�   ø€ ð —/‘/Ó#€Kô   Ó,Ð8Øô )¨Ó5€Iäó  AÐ&ô  Aó  	Aò 	=Ü˜kÔ+>Ó?ò	=äÓFÔ.EÔFÓFÐFò	=ð Ò;˜y¨™|¨y¸©|Ñ;Ð<ð	r   Úcandidate_idÚlookup_modelc                 óL   — | |k(  xs d| v xr | j                  dd«      d   |k(  S )z`Exact match, or ``publisher/slug`` (LM Studio native ids) whose slug equals the configured name.rú   rH   )rÿ   )r  r  s     r   Ú_model_id_matchesr  ±  s7   € à˜<Ñ'Òs¨C°<Ð,?Ò,rÀL×DWÑDWÐX[Ð]^ÓD_Ð`aÑDbÐfrÑDrÐsr   )Únote_blackholerS  Ú
bare_modelrØ  r  c                ó*  — ddl }	 |j                  |t        |«      ¬«      5 }|j                  | › d�d|i¬«      }|j                  dk(  r|j                  «       ndcddd«       S # 1 sw Y   yxY w# t        $ r}|rt        || «       Y d}~yd}~ww xY w)z}Ollama ``/api/show`` JSON for ``bare_model``, or None on any failure (``note_blackhole``: connect timeouts condemn the host).r   Nr×  ú	/api/showr   rÍ  rÚ  )ry   rÝ  r'  ÚpostrÞ  rˆ   r0   rv   )	rS  r   r  rØ  r  ry   rã  rl  rs   s	            r   Ú_ollama_showr  ¶  s‘   € ãðØ�\‰\ '´=ÀÓ3Iˆ\ÓJð 	DÈfØ—;‘; * ¨YÐ7¸vÀzÐ>R�;ÓSˆDØ"&×"2Ñ"2°cÒ"9�4—9‘9”;¸t÷	D÷ 	Dò 	Dûô ò ÙÜ$ S¨*Ô5Üûðús4   †A1 ¢9A%Á	A1 Á%A.Á*A1 Á.A1 Á1	BÁ:BÂBc                 óB   — 	 t        | |¬«      dk(  S # t        $ r Y yw xY w)NrŸ  rË  F)ræ  r0   ©r    r   s     r   Ú_is_ollama_serverr   Ã  s-   € ðô (¨¸'ÔBÀhÑNÐNøÜò Ùðús   ‚ ’	�c                 óú   — t        | «      t        |«      }}t        ||«      sy|› d|› �}t        d|«      }t	        |t
        «      r|dkD  r|S t        |||«      }|�t        |d¬«      nd}|�t        d||«       |S )zbOllama ``/api/show`` context (Modelfile num_ctx, else GGUF max); the value to send as ``num_ctx``.NrU  Úollama_num_ctxr   F©rk  )	rT   rT  r   r«   r+   rr  r  r|  r­   )	rD   r    r   r  rS  Ú	_disk_keyrà  rŒ   r{  s	            r   Úquery_ollama_num_ctxr%  Ì  sŽ   € ä3°EÓ:¼LÈÓ<R�
€JÜ˜X wÔ/ØØ�,˜a 
˜|Ð,€IÜ$Ð%5°yÓA€HÜ�(œCÔ  X°¢\ØˆÜ˜
 G¨ZÓ8€DØ:>Ð:JÔ
˜t°Õ
6ÐPT€CØ
€ÜÐ.°	¸3Ô?Ø€Jr   c                 ó@  — t        | «      }|r|rt        ||«      syt        t        |«      ||«      }|€y|j	                  d«      }t        |t        «      r|rt        d„ |D «       «      S |j	                  d«      }t        |t        «      rt        d„ |D «       «      ryy)z¼True/False when Ollama ``/api/show`` reports vision support (``capabilities`` on 0.6.0+, else
    ``model_info.*.vision.block_count``); None when unreachable, not Ollama, or model unknown.NÚcapabilitiesc              3   óT   K  — | ]   }t        |«      j                  «       d k(  –— Œ" y­w)ÚvisionN©r,   r>   )r?   Úcaps     r   rB   z/query_ollama_supports_vision.<locals>.<genexpr>ç  s    è ø€ Ò@°C”3�s“8—>‘>Ó# xÕ/Ñ@ùs   ‚&(rx  c              3   óR   K  — | ]  }d t        |«      j                  «       v –— Œ! y­w)zvision.block_countNr*  )r?   rn   s     r   rB   z/query_ollama_supports_vision.<locals>.<genexpr>é  s"   è ø€ Ò+kÐY\Ð,@ÄCÈÃHÇNÁNÓDTÔ,TÑ+kùs   ‚%'T)	rT   r   r  rT  r*   r+   rê  r  rŠ   )rD   r    r   r  rŒ   Úcapsrx  s          r   Úquery_ollama_supports_visionr.  Ü  s’   € ô (¨Ó.€JÙ™XÔ->¸xÈÔ-QØÜœ XÓ.°¸ÓD€DØ€|ØØ�8‰8�NÓ#€DÜ�$œÔ¡$ÜÑ@¸4Ô@Ó@Ð@Ø—‘˜,Ó'€JÜ�*œdÔ#¬Ñ+kÐ`jÔ+kÔ(kØØr   Ú	cache_keyÚprobec                 ó¬   — t        j                  «       }t        j                  | «      }|�||d   z
  t        k  r|d   S  |«       }|r||ft        | <   |S )zÃShort-TTL, positive-only memo of a local probe (see _LOCAL_CTX_PROBE_CACHE): a failure during
    a startup race must not suppress the retry once the server is up, so only truthy results memoize.rH   r   )ri   rj   rÌ   r*   Ú_LOCAL_CTX_PROBE_TTL_SECONDS)r/  r0  rž   r£  râ  s        r   Ú_memo_local_prober3  î  s^   € ô �.‰.Ó
€CÜ#×'Ñ'¨	Ó2€FØÐ˜s V¨A¡Y™Ô2NÒNØ�a‰yÐÙ‹W€FÙØ-3°S¨MÔ˜yÑ)Ø€Mr   c                 ó`   ‡ ‡‡— t        dt        ‰ «      ‰j                  d«      fˆˆˆ fd„«      S )uÓ   Provider-agnostic Ollama ``/api/show`` probe (any hostname; non-Ollama servers 404 fast).
    GGUF-first (hosted users can't set num_ctx) â€” the reverse of query_ollama_num_ctx(), hence the namespaced memo key.rÁ  rú   c                  ó    •— t        ‰‰‰ ¬«      S ©NrŸ  )Ú_query_ollama_api_show_uncached©r   r    rD   s   €€€r   rf  z(_query_ollama_api_show.<locals>.<lambda>þ  s(   ø€ ô  lKð  LQð  S[ð  elô  lm€ r   ©r3  rT   r  ©rD   r    r   s   ```r   Ú_query_ollama_api_showr;  û  s4   ú€ ô ˜mÔ-CÀEÓ-JÈHÏOÉOÐ\_ÓL`Ðaõ  dmó  nð  nr   c                 ót   — t        |«      }t        |«      ryt        ||| dd¬«      }|�t        |dd¬«      S dS )uJ   Uncached body of ``_query_ollama_api_show`` â€” one POST to ``/api/show``.Ng      @T)rØ  r  rÖ  )rk  rj  )rT  rr   r  r|  )rD   r    r   rS  rŒ   s        r   r7  r7    sE   € ä˜hÓ'€JÜ˜JÔ'ØÜ˜
 G¨U¸CÐPTÔU€DàHLÐHXÔ °¸tÔDÐbÐ^bÐbr   c                 óP   — | j                  «       }|j                  d«      xs d|v S )uT   Kimi family (``kimi-*``, ``moonshotai/*``) â€” guard against stale 32K underreports.rò   Úmoonshot©r>   rK   ©rD   r>   s     r   Ú_model_name_suggests_kimirA    s(   € à�K‰K‹M€EØ×Ñ˜FÓ#Ò: z°UÐ':Ð:r   c                 ó&   — d| j                  «       v S )uj   MiniMax M3 on any surface â€” models.dev underreport guard and agent_runtime_helpers cache-control gating.rè   ©r>   ©rD   s    r   Ú_model_name_suggests_minimax_m3rE    s   € à˜5Ÿ;™;›=Ð(Ð(r   >   rï   rí   rì   rè   rä   rë   ræ   rÞ   rà   rã   rÛ   rß   rÝ   rÜ   c                 óh  — | j                  «       }t        j                  «       D ��cg c]  \  }}t        ||«      sŒ||f‘Œ }}}|syt	        |d„ ¬«      \  }}|t
        vs||k\  ry|D ��	cg c]  \  }}	t        |«      t        |«      k  sŒ|	‘Œ! }
}}	|t	        |
t        ¬«      k  S c c}}w c c}	}w )zÐTrue when a persisted window is a pre-catalog leftover: the model resolves (longest-key-first) to a
    _PRE_CATALOG_STALE_KEYS key and the cached value is <= the largest shorter matching catch-all (or 256K).Fc                 ó   — t        | d   «      S rc  rd  )Úkvs    r   rf  z0_stale_pre_catalog_cache_entry.<locals>.<lambda>-  s   € ¼sÀ2ÀaÁ5»z€ r   )rn   )rÇ   )r>   ÚDEFAULT_CONTEXT_LENGTHSr�   r_  rë  Ú_PRE_CATALOG_STALE_KEYSrM  rÊ   )rD   r£  rV  rn   rA   ÚmatchesÚspecific_keyÚspecific_valuerŸ   r    Úshorter_valuess              r   Ú_stale_pre_catalog_cache_entryrO  &  s°   € ð —+‘+“-€KÜ.E×.KÑ.KÓ.M×x¡
  UÔQeÐfiÐkvÕQw��UŠ|Ðx€GÑxÙØÜ#& wÑ4IÔ#JÑ €L�.ØÔ2Ñ2°fÀÒ6NØØ$+×J™D˜A˜q¬s°1«v¼¸LÓ8IÓ/I’aÐJ€NÑJØ”S˜Ô1IÔJÑJÐJùó yùó Ks   ¨B(½B(Á-B.ÂB.c                 óP   — | j                  «       }|j                  d«      xs d|v S )ug   MiniMax family (``minimax*``, ``minimaxai/*``) â€” guard against stale 32K underreports (real: 204.8K).ré   z
minimaxai/r?  r@  s     r   Ú_model_name_suggests_minimaxrQ  4  s(   € à�K‰K‹M€EØ×Ñ˜IÓ&Ò?¨,¸%Ð*?Ð?r   c                 ó2   — t        | «      xs t        | «      S )z8Model families known to be wrongly underreported as 32K.)rA  rQ  rD  s    r   Ú*_model_name_suggests_stale_32k_underreportrS  :  s   € ä$ UÓ+ÒRÔ/KÈEÓ/RÐRr   c                 ó^   ‡ ‡‡— t        t        ‰ «      ‰j                  d«      fˆˆˆ fd„«      S )zJLocal-server context probe, short-TTL cached (see _LOCAL_CTX_PROBE_CACHE).rú   c                  ó    •— t        ‰‰‰ ¬«      S r6  )Ú$_query_local_context_length_uncachedr8  s   €€€r   rf  z-_query_local_context_length.<locals>.<lambda>A  s(   ø€ ô  ]Að  BGð  IQð  [bô  ]c€ r   r9  r:  s   ```r   r   r   ?  s/   ú€ äÔ4°UÓ;¸X¿_¹_ÈSÓ=QÐRõ  Ucó  dð  dr   c                 óL   — t        | t        t        f«      r| rt        | «      S d S r9   )r+   rr  r’   )rA   s    r   Ú_positive_intrX  D  s    € Ü# E¬C´¨<Ô8¹UŒ3ˆu‹:ÐLÈÐLr   rß  c           	      ó^  — | j                  |› d�«      }|j                  dk7  ry|j                  «       j                  dg «      D ]f  }t        |j                  dd«      |«      st        |j                  dd«      |«      sŒ<t	        d„ d	„ |j                  d
g «      D «       D «       d«      c S  y)zxLM Studio native /api/v1/models (the OpenAI-compat list omits context);
    loaded-instance config is the runtime value.rÈ  rÚ  Nr½   rn   r   rL  c              3   ó&   K  — | ]	  }|€Œ|–— Œ y ­wr9   r:   ©r?   r{  s     r   rB   z$_lmstudio_context.<locals>.<genexpr>P  s$   è ø€ ò  d ð  TWñ  Tcœñ  dùrû  c              3   óp   K  — | ].  }t        |j                  d i «      j                  d«      «      –— Œ0 y­w)r_  r  N©rX  r*   )r?   r`  s     r   rB   z$_lmstudio_context.<locals>.<genexpr>P  s3   è ø€ ò  )PÐim¬°t·x±xÀÈ"Ó7M×7QÑ7QÐRbÓ7c×)dñ  )Pùs   ‚46r^  )r*   rÞ  rˆ   r  rˆ  )rã  rß  rD   rl  r‹  s        r   Ú_lmstudio_contextr^  H  sÉ   € ð �:‰:˜˜ nÐ5Ó6€DØ×Ñ˜3ÒØØ�Y‰Y‹[�_‰_˜X rÓ*ò kˆÜ˜QŸU™U 5¨"Ó-¨uÔ5Ô9JÈ1Ï5É5ÐQUÐWYË?Ð\aÕ9bÜñ  dñ  )PÐqr×qvÑqvð  xJð  LNó  rOô  )Pô  dð  fjó  kò  kðkð r   c                 ó  — ddl }d|› �dfD ]i  }	 | j                  |› |› �«      }|j                  dk7  rŒ)t	        |j                  «       j                  d«      xs i j                  d«      «      }|€Œg|c S  y# |j                  $ r Y  yw xY w)z¾llama.cpp /props: the RUNTIME n_ctx, answered by the router even for a not-yet-loaded model
    (while /v1/models has meta=null), so a lazily-loaded model doesn't fall to a family catch-all.r   Nz/props?model=rÐ  rÚ  rÒ  r  )ry   r*   Ú	HTTPErrorrÞ  rX  rˆ   )rã  rS  rD   ry   Ú
props_pathrl  r  s          r   Ú_llamacpp_contextrb  T  s¥   € ó Ø& u gÐ.°Ð9ò 	ˆ
ð	Ø—:‘:  ¨Z¨LÐ9Ó:ˆDð ×Ñ˜sÒ"ØÜ˜tŸy™y›{Ÿ™Ð/LÓMÒSÐQS×XÑXÐY`ÓaÓbˆØÑØŠLð	ð øð �‰ò 	Úð	ús   �A9Á9BÂBc                 ó¦  ‡— | j                  |› d�«      }|j                  dk7  ry|j                  «       j                  dg «      }t        ˆfd„|D «       d«      }|€t	        |«      dk(  r|d   }|€y||j                  d«      xs i fD �cg c]  }t        |t        «      sŒ|‘Œ }}d	„ t        fD ]  }|D ]  }	 ||	«      }
|
€Œ|
c c S  Œ yc c}w )
zp/v1/models list: match by id, else the sole model on single-model servers (llama.cpp reports a GGUF path as id).z
/v1/modelsrÚ  NrŒ   c              3   ó~   •K  — | ]4  }t        |t        «      sŒt        |j                  d d«      ‰«      sŒ1|–— Œ6 y­w)rL  r   N)r+   rŠ   r  r*   )r?   r‹  rD   s     €r   rB   z._openai_models_list_context.<locals>.<genexpr>k  s5   øè ø€ Òp˜!¬j¸¼DÕ.AÔFWÐXY×X]ÑX]Ð^bÐdfÓXgÐinÕFo”AÑpùs   ƒ=™=¶=rH   r   Úmetac                 ó6   — t        | j                  d«      «      S )Nr  r]  )Úsrcs    r   rf  z-_openai_models_list_context.<locals>.<lambda>r  s   € œ}¨S¯W©W°WÓ-=Ó>€ r   )r*   rÞ  rˆ   rˆ  rM  r+   rŠ   r  )rã  rS  rD   rl  Úmodels_listr™  ÚsÚsourcesrz  r  r{  s     `        r   Ú_openai_models_list_contextrk  e  sæ   ø€ à�:‰:˜˜ JÐ/Ó0€DØ×Ñ˜3ÒØØ—)‘)“+—/‘/ &¨"Ó-€KÜÓp˜{ÔpÐrvÓw€GØ€œ3˜{Ó+¨qÒ0Ø˜a‘.ˆØ€Øà" G§K¡K°Ó$7Ò$=¸2Ð>ÖV�QÄ*ÈQÔPTÕBUŠqÐV€GÐVÙ>Ô@bÐcò ˆØò 	ˆFÙ˜“.ˆCØ‰Ø”
ñ	ðð
 ùò Ws   ÂCÂ"Cc                 óH  ‡ ‡
‡‡— ddl }t        ‰ «      Š t        |«      Št        t	        |«      «      Št        ‰«      ry	 t        ||¬«      }dt        t           fˆ ˆfd„}dt        t           fˆ ˆfd„}|ˆˆ fd„ˆ ˆfd„d	œj                  |«      }|r|gng |ˆ ˆfd
„gz   }	 |j                  dt        |«      ¬«      5 Š
t        d„ ˆ
fd„|D «       D «       d«      cddd«       S # t        $ r d}Y Œ¥w xY w# 1 sw Y   yxY w# t        $ r}	t        |	‰«       Y d}	~	yd}	~	ww xY w)z4Query a local server for the model's context length.r   NrŸ  r!   c                 óŒ   •— | j                  ‰› d�d‰i¬«      }|j                  dk(  rt        |j                  «       d¬«      S d S )Nr  r   rÍ  rÚ  Fr#  )r  rÞ  r|  rˆ   ©rã  rl  rD   rS  s     €€r   Ú_ollama_ctxz9_query_local_context_length_uncached.<locals>._ollama_ctx†  sJ   ø€ ð �{‰{˜j˜\¨Ð3¸6À5¸/ˆ{ÓJˆØFJ×FVÑFVÐZ]ÒF]Ô# D§I¡I£K¸EÔBÐgÐcgÐgr   c                 ó„   •— | j                  ‰› d‰› �«      }|j                  dk(  rt        |j                  «       «      S d S )Nz/v1/models/rÚ  )r*   rÞ  r  rˆ   rn  s     €€r   Ú_model_detail_ctxz?_query_local_context_length_uncached.<locals>._model_detail_ctx‹  sB   ø€ à�z‰z˜Z˜L¨°E°7Ð;Ó<ˆØBF×BRÑBRÐVYÒBYÔ1°$·)±)³+Ó>ÐcÐ_cÐcr   c                 ó   •— t        | ‰‰«      S r9   )r^  )rã  rß  rD   s    €€r   rf  z6_query_local_context_length_uncached.<locals>.<lambda>‘  s   ø€ Ô$5°f¸lÈEÓ$R€ r   c                 ó   •— t        | ‰‰«      S r9   )rb  ©rã  rD   rS  s    €€r   rf  z6_query_local_context_length_uncached.<locals>.<lambda>’  s   ø€ Ô#4°V¸ZÈÓ#O€ r   )rË  rÇ  rÎ  c                 ó   •— t        | ‰‰«      S r9   )rk  rt  s    €€r   rf  z6_query_local_context_length_uncached.<locals>.<lambda>”  s   ø€ ÔMhÐioÐq{ð  ~Có  ND€ r   ç      @r×  c              3   ó&   K  — | ]	  }|€Œ|–— Œ y ­wr9   r:   r[  s     r   rB   z7_query_local_context_length_uncached.<locals>.<genexpr>—  s   è ø€ Ò_ ÈsÉœÑ_ùrû  c              3   ó.   •K  — | ]  } |‰«      –— Œ y ­wr9   r:   )r?   r0  rã  s     €r   rB   z7_query_local_context_length_uncached.<locals>.<genexpr>—  s   øè ø€ Ò(K¸5©¨v¯Ñ(Kùs   ƒ)ry   rT   rT  rR  rO  rr   ræ  r0   r   rr  r*   rÝ  r'  rˆ  rv   )rD   r    r   ry   rÆ  ro  rq  ÚtypedÚprobesrs   rã  rß  rS  s   `         @@@r   rV  rV  z  s5  û€ ãÜ" 5Ó)€EÜ˜hÓ'€JÜ%Ô&;¸HÓ&EÓF€LÜ˜JÔ'ØðÜ.¨xÀÔIˆðhœx¬™}ö hð
d¤X¬c¡]ö dð
 ÜRÜOñ÷ 
�cˆ+Óð	 
ñ
 ˆu‰g BÐ+<ô  ?Dð  +Eñ  E€Fð2Ø�\‰\ #¬}¸WÓ/Eˆ\ÓFð 	gÈ&ÜÑ_Ó(KÀFÔ(KÔ_ÐaeÓf÷	gñ 	gøô% ò ØŠðú÷$	gð ûô ò 2Ü   j×1Ð1Øûð2úsH   Á C% Â#D Â?C6Ã	D Ã%C3Ã2C3Ã6C?Ã;D Ã?D Ä	D!ÄDÄD!c                 ó&   — | j                  dd«      S )zYDots -> dashes so Nous ids (claude-opus-4-6) compare with OpenRouter's (claude-opus-4.6).rª  r
  )r  rD  s    r   r^  r^  �  s   € à�=‰=˜˜cÓ"Ð"r   c                 ó<  — |r!t        |t        «      r|j                  d«      ry	 |j                  d«      j	                  d«      }|ddœ}t        «        t        j                  |› d�|dt        |«      ¬	«      }|j                  d
k7  ry|j                  «       j                  dg «      D ]C  }|j                  d«      | k(  r|j                  d«      nd}t        |t        «      sŒ;|dkD  sŒA|c S  	 y# t        $ r }t        j                  d|«       Y d}~yd}~ww xY w)u  Anthropic /v1/models max_input_tokens; OAuth tokens (sk-ant-oat*) 401 and are skipped.

    ``api_key`` may be a ``key_cmd`` callable token source; the metadata probe never mints â€” a
    callable is not a Console key, so the lookup is skipped like an OAuth token (#114967).
    z
sk-ant-oatNrú   rK  z
2023-06-01)z	x-api-keyzanthropic-versionz/v1/models?limit=1000rI  rd  rÚ  rŒ   rL  r  r   z%Anthropic /v1/models query failed: %s)r+   r,   rK   r  Úremovesuffixr   r   r*   r6   rÞ  rˆ   rr  r0   rk   rl   )	rD   r    r   rF  rÙ  rl  r‹  r{  r¡   s	            r   Ú_query_anthropic_context_lengthr~  ¢  s  € ñ œ* W¬cÔ2°g×6HÑ6HÈÔ6VØðAØ�‰˜sÓ#×0Ñ0°Ó7ˆØ '¸lÑKˆÜÔÜ�|‰|˜t˜fÐ$9Ð:ÀGÐU\Ôe}ð  Gó  fHô  IˆØ×Ñ˜sÒ"ØØ—‘“—‘ ¨Ó,ò 	ˆAØ/0¯u©u°T«{¸eÒ/C�!—%‘%Ð*Ô+ÈˆCÜ˜#œsÕ#¨¨a«Ø’
ñ	ð øô ò AÜ�‰Ð<¸a×@Ð@ØûðAús1   ¦A#C2 Â
AC2 Ã%C2 Ã+C2 Ã/C2 Ã2	DÃ;DÄDi€& zgpt-5.1-codex-maxzgpt-5.1-codex-minizgpt-5.3-codexzgpt-5.2-codexúgpt-daybreak-blue-latestzgpt-5.2Ú_CODEX_OAUTH_CONTEXT_FALLBACKi » )zgpt-5.6rÑ   rÒ   rÓ   Ú/_CODEX_OAUTH_VERIFIED_ABOVE_ADVERTISED_PREFIXES)r×   r  rÐ   Ú,_CODEX_OAUTH_VERIFIED_ABOVE_ADVERTISED_EXACTz-900k)rÖ   rÕ   rÔ   rÑ   rÒ   rÓ   z^\d{4}-\d{2}-\d{2}$c                 ól   — | xs dj                  «       j                  «       j                  dd«      d   S )a*  Lowercased slug without ``vendor/`` (display/auxiliary callers pass ``openai/gpt-5.6-sol-900k``).

    Display/auxiliary callers pass ids like ``openai/gpt-5.6-sol-900k``; the main-agent path normalizes the
    namespace away earlier, but this resolver must accept both shapes (#92797 review).
    r   rú   rH   rû   )rN   r>   rÿ   rD  s    r   Ú_bare_codex_slugr„  Û  s2   € ð ŠK�R×ÑÓ ×&Ñ&Ó(×/Ñ/°°QÓ7¸Ñ;Ð;r   c                 óŽ   ‡— t        | «      Š‰r‰j                  t        «      ry‰t        v xs t	        ˆfd„t
        D «       «      S )ziSingle source of truth for ``-900k`` eligibility (picker, resolution, /model validation, wire stripping).Fc              3   ó’   •K  — | ]>  }‰j                  |d z   «      xr$ t        j                  ‰t        |«      dz   d «      –— Œ@ y­w)r
  rH   N)rK   Ú_CODEX_900K_SNAPSHOT_RErP   rM  )r?   rF  Úslugs     €r   rB   z%is_codex_900k_base.<locals>.<genexpr>ê  sG   øè ø€ ò 5Ø`dˆ�‰˜˜s™
Ó#Ò[Ô(?×(EÑ(EÀdÌ3ÈtË9ÐWXÉ=È>ÐFZÓ([Ó[ñ5ùs   ƒAA)r„  rL  ÚCODEX_CONTEXT_VARIANT_SUFFIXÚ_CODEX_900K_ELIGIBLE_BASESr  Ú_CODEX_900K_SNAPSHOT_BASES)rD   rˆ  s    @r   Úis_codex_900k_baserŒ  ä  sJ   ø€ ä˜EÓ"€DÙ�4—=‘=Ô!=Ô>ØàÔ-Ð-ò ´ó 5ô iCô5ó 2ð r   c                 óŽ   — t        | «      }|j                  t        «      r|dt        t        «        nd}|�t	        |«      r|S dS )zhLowercased eligible base of a VALID ``-900k`` variant, else None (``gpt-5.5-900k`` is an invalid alias).N)r„  rL  r‰  rM  rŒ  )rD   rˆ  rF  s      r   Ú_codex_variant_baserŽ  ï  sI   € ä˜EÓ"€DØ9=¿¹ÔGcÔ9dˆ4Ð4”3Ô3Ó4Ð4Ñ5Ðjn€DØÐ#Ô(:¸4Ô(@ˆ4ÐJÀdÐJr   c                 ó   — t        | «      duS )uQ   Suffix AND eligible base â€” ``gpt-5.5-900k`` is an invalid alias, not a variant.N)rŽ  rD  s    r   Úis_codex_context_variantr�  ö  s   € ä˜uÓ%¨TÐ1Ð1r   c                 ój   — | xs dj                  «       }t        |«      �|dt        t        «        S |S )z½Wire-safe slug with a VALID ``-900k`` suffix removed (vendor prefix kept); an ineligible alias is
    returned unchanged so it fails honestly at the API instead of running as another model.r   N)rN   rŽ  rM  r‰  )rD   r  s     r   Ú"strip_codex_context_variant_suffixr’  û  s=   € ð Š;�B×
Ñ
Ó
€CÜ8KÈCÓ8PÐ8\ˆ3Ð3”#Ô2Ó3Ð3Ð4ÐeÐbeÐer   Ú
model_barec                 ó   — t        | «      S )z0Picker-side alias of :func:`is_codex_900k_base`.)rŒ  )r“  s    r   Úhas_codex_context_variantr•    s   € ä˜jÓ)Ð)r   c                 ó    ‡— t        | «      Š‰€yt        j                  ‰«      }|�|S t        ˆfd„t        j                  «       D «       d«      S )z`Live-verified cap for a VALID ``-900k`` variant only; base slugs and ineligible aliases -> None.Nc              3   óf   •K  — | ](  \  }}‰|k(  s‰j                  |d z   |dz   f«      sŒ%|–— Œ* y­w)r
  rª  Nrý   )r?   rn   r{  rF  s      €r   rB   z/_verified_codex_ctx_for_slug.<locals>.<genexpr>  se   øè ø€ ò  X™˜˜cÐ`dÐhkÒ`kÐos×o~Ño~ð  ADð  GJñ  AJð  LOð  RUñ  LUð  @Võ  pW”ñ  Xùó   ƒ&1ª1)rŽ  r‚  r*   rˆ  r�  r�   )r“  ÚexactrF  s     @r   Ú_verified_codex_ctx_for_slugrš    s^   ø€ ä˜zÓ*€DØ€|ØÜ8×<Ñ<¸TÓB€EØÐØˆÜó  XÔ%T×%ZÑ%ZÓ%\ô  Xð  Z^ó  _ð  _r   Ú_codex_oauth_context_cacheÚ_codex_oauth_max_context_cachez,https://chatgpt.com/backend-api/codex/modelsz99.0.0z0.0.0c              #   ó2   K  — | ]  }t         › d |› �–— Œ y­w)z?client_version=N)ÚCODEX_MODELS_CATALOG_ENDPOINTr  s     r   rB   rB   "  s%   è ø€ ò "à	ô %Ð%Ð%5°a°SÔ9ñ"ùs   ‚r*   c                 óð   — d}t         D ]h  } | |«      }|j                  }|dk7  rŒ|j                  «       }t        |t        «      r|j                  d«      nd}t        |t        «      sŒa|sŒd||fc S  g |fS )a!  ``(models, last_status)`` from the first catalog URL that answers HTTP 200 with a non-empty
    ``models`` list; ``get(url)`` is any client returning an object with ``status_code``/``json()``.
    An empty or non-200 answer on the newest-client URL falls through to the ``0.0.0`` sentinel.NrÚ  r½   )ÚCODEX_MODELS_CATALOG_URLSrÞ  rˆ   r+   rŠ   r*   rê  )r*   rs  rÂ  rl  rŒ   Úentriess         r   Úfetch_codex_catalog_entriesr¢  (  s|   € ð !€FÜ(ò #ˆÙ�3‹xˆØ×!Ñ!ˆØ�SŠ=ØØ�y‰y‹{ˆÜ(2°4¼Ô(>�$—(‘(˜8Ô$ÀDˆÜ�gœtÕ$ªØ˜F�?Ò"ð#ð ˆvˆ:Ðr   Úaccess_tokenc                 ól   — t        j                  | j                  d«      «      j                  «       dd S )z4Non-secret cache key for a Codex OAuth access token.r„   Nr®  )ÚhashlibÚsha256ÚencodeÚ	hexdigest©r£  s    r   Ú_codex_oauth_token_fingerprintrª  9  s,   € ä�>‰>˜,×-Ñ-¨gÓ6Ó7×AÑAÓCÀCÀRÐHÐHr   c                 óB  ‡— t        j                   «       }t        | «      }t        j                  |«      }|�||d   z
  t        k  r|d   dfS ddlm} dd| › �i || «      ¥Š	 t        «        t        ˆfd„«      \  }}|d	k7  rt        j                  d
|«       i dfS 	 i }i }	|D ]¯  }
t        |
t        «      r2|
j                  d«      |
j                  d«      |
j                  d«      fnd\  }}}t        |t        «      sŒ\t        |t        «      sŒm|dkD  sŒs|||j!                  «       <   t        |t        «      sŒ—|dkD  sŒ�||	|j!                  «       <   Œ± |r||ft        |<   |	t"        |<   |dfS # t        $ r$}t        j                  d|«       i dfcY d}~S d}~ww xY w)aO  Codex catalogue ``{slug: context_window}`` plus whether it came from HTTP. Cached per token
    fingerprint (windows vary by entitlement); ``max_context_window`` lands in
    ``_codex_oauth_max_context_cache`` under the same key. An in-process hit reports False: not a
    fresh provider confirmation, must not drive persistent writes.NrH   r   F)Úcodex_account_headersr#  r$  c                 óF   •— t        j                  | ‰dt        «       ¬«      S )NrI  rd  )r   r*   r6   )rÂ  rÙ  s    €r   rf  z@_fetch_codex_oauth_context_lengths_with_source.<locals>.<lambda>O  s   ø€ œŸ™ S°'À7ÔSkÓSmÔn€ r   rÚ  zHCodex /models probe returned HTTP %s; falling back to hardcoded defaultszCodex /models probe failed: %srˆ  r  Úmax_context_window)NNNT)ri   rª  r›  r*   Ú_CODEX_OAUTH_CONTEXT_CACHE_TTLÚagent.codex_headersr¬  r   r¢  rk   rl   r0   r+   rŠ   r,   rr  rN   rœ  )r£  rž   r/  r£  r¬  r¡  rs  rs   râ  Ú
max_resultrì  rˆ  r{  Úmax_ctxrÙ  s                 @r   Ú._fetch_codex_oauth_context_lengths_with_sourcer³  >  s·  ø€ ô
 �)‰)‹+€CÜ.¨|Ó<€IÜ'×+Ñ+¨IÓ6€FØÐ˜c F¨1¡I™oÔ0NÒNØ�a‰y˜%ÐÐõ :Ø '¨,¨Ð 8Ð`Ñ<QÐR^Ó<_Ð`€Gð
ÜÔÜ5Ûnó
‰ˆ�ð �SŠ=Ü�L‰LÐcÐekÔlØ�u�9Ðð ð  €FØ!#€JØò 3ˆÜoyÐz~ô  AEô  pF˜dŸh™h vÓ.°·±Ð9IÓ0JÈDÏHÉHÐUiÓLjÑkð  L^Ñˆˆc�7Ü�dœCÕ ¤Z°´SÕ%9¸cÀA»gØ#&ˆF�4—:‘:“<Ñ Ü˜'¤3Õ'¨G°a«KØ+2�
˜4Ÿ:™:›<Ò(ð3ñ Ø17¸°Ô" 9Ñ-Ø4>Ô& yÑ1Ø�4ˆ<Ðøô ò Ü�‰Ð5°sÔ;Ø�5ˆyÕûðús   Á$9E1 Å1	FÅ:FÆFÆFc                 ó   ‡‡	— t        | «      j                  «       Š	‰	syddt        dt        dt        t           dt
        t        t        f   fˆ	fd„}t        t        ‰	«      «      Š|rjt        |«      \  }}t        j                  t        |«      i «      }‰|v r‰nt        ˆfd„|D «       d«      }|�  |||   |rd	nd
|j                  |«      «      S t        t        ‰j                  «       «      }|r ||d   d«      S dS )uð   ``(context_length, source)`` for a Codex OAuth slug. source: "live" (fresh authenticated probe â€”
    the only one eligible for persistent writes), "memory" (same-token in-process hit), "fallback"
    (static table), or "" when unresolved.©Nr   Nr{  r  Úcatalog_maxr!   c                 ó�   •— t        ‰«      }|�5| t        k(  r,|rt        ||«      n|}t        j	                  d‰| |«       ||fS | |fS )z¾Lift an EXACT stale 272K advertisement to the verified cap for opted-in ``-900k`` variants only,
        never above the catalog's own ``max_context_window`` when it publishes one (#105443).zDCodex OAuth context for %s: advertised %d raised to live-verified %d)rš  Ú!_CODEX_OAUTH_STALE_ADVERTISED_CTXrR  rk   rl   )r{  r  r¶  Úbumpedr“  s       €r   Ú_apply_verified_bumpzM_resolve_codex_oauth_context_length_with_source.<locals>._apply_verified_bumpl  sW   ø€ ô .¨jÓ9ˆØÐ #Ô)JÒ"JÙ1<”S˜ Ô-À&ˆFÜ�L‰LÐ_ÐakÐmpÐrxÔyØ˜6�>Ð!Ø�Fˆ{Ðr   c              3   óf   •K  — | ](  }|j                  «       ‰j                  «       k(  sŒ%|–— Œ* y ­wr9   rC  )r?   ri  Úlookup_bares     €r   rB   zB_resolve_codex_oauth_context_length_with_source.<locals>.<genexpr>  s,   øè ø€ Ò<qÀ1ÐPQ×PWÑPWÓPYÐ]h×]nÑ]nÓ]pÓPp¼QÑ<qùr˜  ÚliveÚmemoryrH   Úfallbackr9   )rT   rN   rr  r,   r   r	   r„  r’  r³  rœ  r*   rª  rˆ  ri  r€  r>   )
rD   r£  rº  r½  Úfresh_probeÚlive_maxrˆ  Úhitr¼  r“  s
           @@r   Ú/_resolve_codex_oauth_context_length_with_sourcerÃ  e  s  ù€ ô (¨Ó.×4Ñ4Ó6€JÙØñ¤#ð ¬sð ÄÌ#Áð ÔZ_Ô`cÔehÐ`hÑZiõ ô #Ô#EÀjÓ#QÓR€KÙÜJÈ<ÓXÑˆˆkÜ1×5Ñ5Ô6TÐUaÓ6bÐdfÓgˆà)¨TÑ1‰{´tÓ<qÈÔ<qÐswÓ7xˆØÐÙ'¨¨T©
¹k±FÈxÐYa×YeÑYeÐfjÓYkÓlÐlÜ
Ô:¸K×<MÑ<MÓ<OÓ
P€CÙ7:Ñ  A¡¨
Ó3ÐJÀ
ÐJr   c                 óÀ  ‡ ‡‡‡— |rt        ‰ ||¬«      }|�|dfS t        «       }dt        dt        dt        t
           fd„}‰ j                  «       t        ‰ «      j                  «       cŠŠdt        fˆˆfd„Šdt        dt        fˆfd	„}dt        dt        fˆfd
„}ˆ fd„||fD ]7  }|j                  «       D ]"  \  }	}
 ||	«      r	 ||	|
«      nd}|€Œ|dfc c S  Œ9 y)u  ``(context_length, source)`` for a Nous Portal model: portal /v1/models is authoritative
    ("portal"). Fallback matches OR's prefixed ids against the bare Nous id with dot/dash
    normalisation ("openrouter" â€” callers must NOT persist it, or a portal blip freezes the wrong value).rŸ  NÚportalÚor_idr“   r!   c                 ó|   — |j                  d«      }|�(|dk  r#t        | «      rt        j                  d|| «       y|S )zMContext length minus the known stale 32K underreports (same guard as step 6).r  Nró   zyRejecting OpenRouter metadata context=%s for %r (known 32K underreport, Nous path); falling through to hardcoded defaults)r*   rS  rk   r¥  )rÆ  r“   r{  s      r   Ú	_safe_ctxz/_resolve_nous_context_length.<locals>._safe_ctx�  sN   € à�i‰iÐ(Ó)ˆØˆ?˜s eš|Ô0ZÐ[`Ô0aÜ�K‰Kð  Tð  VYð  [`ô  aØØˆ
r   c                 ó”   •— d| v r| j                  dd«      d   n| }|j                  «       ‰ft        |«      j                  «       ‰ffS rD  )rL   r>   r^  )rÆ  rÅ  rV  r^   s     €€r   Ú_pairsz,_resolve_nous_context_length.<locals>._pairs—  sK   ø€ Ø),°©ˆu�{‰{˜3 Ó" 1Ò%¸5ˆØ—‘“˜{Ð+Ô.FÀtÓ.L×.RÑ.RÓ.TÐV`Ð-aÐbÐbr   c                 ó4   •— t        d„  ‰| «      D «       «      S )Nc              3   ó,   K  — | ]  \  }}||k(  –— Œ y ­wr9   r:   ©r?   r’  r†  s      r   rB   z?_resolve_nous_context_length.<locals>._exact.<locals>.<genexpr>›  s   è ø€ ÒLÑ*:¨)°U�9 Õ%ÑLùs   ‚r  ©rÆ  rÊ  s    €r   Ú_exactz,_resolve_nous_context_length.<locals>._exactš  s   ø€ ÜÑL¹fÀU»mÔLÓLÐLr   c                 ó4   •— t        d„  ‰| «      D «       «      S )Nc              3   óš   K  — | ]C  \  }}|j                  |«      xr) t        |«      t        |«      k(  xs |t        |«         d v –— ŒE y­w)z-:.N)rK   rM  rÍ  s      r   rB   z@_resolve_nous_context_length.<locals>._prefix.<locals>.<genexpr>�  sa   è ø€ ò  [ñ  yIð  yBð  DI�9×'Ñ'¨Ó.Òs´C¸	³NÄcÈ%ÃjÑ4PÒ4rÐT]Ô^aÐbgÓ^hÑTiÐmrÐTrÓsñ  [ùs   ‚A	Ar  rÎ  s    €r   Ú_prefixz-_resolve_nous_context_length.<locals>._prefixœ  s3   ø€ Üñ  [ñ  MSð  TYó  MZô  [ó  [ð  	[r   c                 ó   •— | ‰k(  S r9   r:   )rÆ  rD   s    €r   rf  z._resolve_nous_context_length.<locals>.<lambda>   s   ø€  %¨5¡.€ r   r2  rµ  )
rš  rX  r,   rŠ   r   rr  r>   r^  r   r�   )rD   r    r   Ú
portal_ctxr'  rÈ  rÏ  rÒ  ÚmatcherrÆ  r“   r{  rÊ  rV  r^   s   `           @@@r   Ú_resolve_nous_context_lengthrÖ  †  s  û€ ñ Ü5°e¸XÈwÔWˆ
ØÐ!Ø˜xÐ'Ð'Ü#Ó%€Hðœð ¤Tð ¬h´s©mó ð $Ÿk™k›mÔ-EÀeÓ-L×-RÑ-RÓ-TÐ€K�ðc”cö cðM”cð Mœdõ Mð[”sð [œtõ [ó 1°&¸'ÐBò )ˆØ$ŸN™NÓ,ò 	)‰LˆE�5Ù-4°U¬^‘)˜E 5Ô)ÀˆCØ‰Ø˜LÐ(Ô(ñ	)ð)ð
 r   rŸ  c                óŒ  — |dk  t         j                  d|f|dk  xr t        | «      t         j                  d|d›ft	        | |«      t         j                  d|d›ff}|D ]"  \  }}}}|sŒ ||| ||«       t        | |«        y t        |«      dk(  rt         j                  d	| |«       yt        |«      rt        | |||¬
«      S |S )zôStep 1 of get_model_context_length: accept, repair, or drop a persisted entry. Returns the
    value to use, or None to fall through to live resolution. Order matters: a value must be
    rejected as bogus before any provider-specific handling.r   z;Dropping non-positive cache entry %s@%s -> %s; re-resolvingró   zlDropping stale cached context entry %s@%s -> %s (known 32K underreport); re-resolving via hardcoded defaultsr™   zWDropping stale pre-catalog cache entry %s@%s -> %s; re-resolving via hardcoded defaultsNr3  z@Bypassing persistent cache for %s@%s (Nous portal authoritative)rŸ  )
rk   rÉ   rS  r¥  rO  r¦  rC  rl   rÁ  r¨  )	rD   r    r£  r   Ú
drop_rulesrÂ  ÚlogÚmsgÚshowns	            r   Ú_validate_cached_context_lengthrÜ  ¨  sú   € ð 
�1‰”f—n‘nÐ&cÐekÐlØ	�5‰Ò	NÔGÈÓNÔPV×P[ÑP[Ø	wð  }Cð  DEð  |Fð	Hä	'¨¨vÓ	6¼¿¹Ø	bÐgmÐnoÐfpð	sð	€Jð !+ò ÑˆˆS�#�uÚÙ��U˜H eÔ,Ü-¨e°XÔ>Ùð	ô   Ó)¨VÒ3Ü�‰ÐWÐY^Ð`hÔiØô ˜Ô"Ü5°e¸XÀvÐW^Ô_Ð_Ø€Mr   c                 óÊ   — t        j                  «       }t        t        j	                  «       «      D ](  \  }}||z
  t
        k\  sŒt        j                  |d«       Œ* | t        v S )zLPrune expired failures and check this home/endpoint/model/region's cooldown.N)ri   rj   rê  rÍ   r�   Ú"_BEDROCK_PROBE_FAILURE_TTL_SECONDSr²  )rn   rž   r�  Ú	failed_ats       r   Ú_bedrock_probe_failed_recentlyrà  Ê  s\   € ä
�.‰.Ó
€CÜ#Ô$@×$FÑ$FÓ$HÓIò =Ñˆ�)Ø�‰?Ô@Ó@Ü(×,Ñ,¨X°tÕ<ð=ð Ô.Ð.Ð.r   c                 óz   — |dk(  xs5 t        | xr( t        | «      j                  d«      xr t        | d«      «      S )NÚbedrockzbedrock-runtime.zamazonaws.com)r   r   rK   r   rŽ  s     r   r·  r·  Ó  sF   € Ø�yÑ ò ¤DØò 	=Ô& xÓ0×;Ñ;Ð<NÓOò 	=Ü! (¨OÓ<ó%ð r   c                 óD  — 	 ddl m}m}m} |xs d}t        | |d¬«      }|�|dkD  r|S |rt        j                  d|«      nd}|r|j                  d«      nd	}|s)t        j                  t        «      5   |«       }ddd«       dd
lm}	  |	«       |j                  d«      | |f}
|rXt        |
«      sM || |«      }|r't!        | ||d¬«       t"        j%                  |
d«       |S t'        j(                  «       t"        |
<    || d¬«      S # t        $ r Y yw xY w# 1 sw Y   ŒœxY w)aj  Step 1b: Bedrock static table + one cached live probe (Bedrock exposes no context window via
    metadata APIs); None when boto3 is absent. Only provider-confirmed windows from a probe
    or runtime error are reused. The table answers a call, never the cache. Keys use base_url,
    or synthetic bedrock:// when absent, consistently with provider-error writers.r   )Úget_bedrock_context_lengthÚprobe_bedrock_context_lengthÚresolve_bedrock_regionNr¶  Tr¹  zbedrock-runtime\.([a-z0-9-]+)\.rH   r   rÂ  rú   râ  )rB  F)r0  )Úagent.bedrock_adapterrä  rå  ræ  ÚImportErrorr¿  r[  r]  rÙ  r”  r•  r0   r€   rÃ  r  rà  r¸  rÍ   r²  ri   rj   )rD   r    rä  rå  ræ  Úcache_key_urlr£  Ú_mÚregionrÃ  r�  Úprobeds               r   Ú_resolve_bedrock_context_lengthrí  Ú  s#  € ð
ßzÑzð Ò, €MÜ& u¨mÈtÔT€FØÐ˜f qšjØˆñ
 EMŒ�‰Ð5°xÔ	@ÐRV€BÙˆR�X‰X�aŒ[ B€FÙÜ× Ñ ¤Ó+ñ 	.Ù+Ó-ˆF÷	.å0ÙÓ! =×#7Ñ#7¸Ó#<¸eÀVÐL€HÙÔ4°XÔ>Ù-¨e°VÓ<ˆÙô )¨°¸vÐPYÕZÜ(×,Ñ,¨X°tÔ<ØˆMÜ15·±Ó1AÔ$ XÑ.Ù% e°5Ô9Ð9øô7 ò Ùðú÷	.ð 	.ús   ‚
D Á3DÄ	DÄDÄDc                 óŽ  — t        | ||¬«      }|�|S t        |«      rt        | |||«      nd}|r|S t        | ||¬«      }|�t	        | |||«       |S t
        j                  d| |t        d›«       t        t        | j                  «       «      }|r%t
        j                  d|d   d›| |d   «       |d   S t        | |«       t        S )zaSteps 2-3 for a truly custom endpoint: /models, local probes, Ollama /api/show, catalog, default.rŸ  Nu‘   Could not detect context length for model %r at %s â€” defaulting to %s tokens (probe-down). Set model.context_length in config.yaml to override.r™   zUUsing hardcoded context length %s for model %r (custom endpoint, catalog match on %r)rH   r   )rš  rÁ  r¢  r;  r™  rk   r¥  rÊ   ri  rI  r>   rË   )rD   r    r   rB  r  r¡  r{  rÂ  s           r   Ú'_resolve_custom_endpoint_context_lengthrï  ÿ  sõ   € ä5°e¸XÈwÔW€NØÐ!ØÐô TeÐemÔSnÔ+¨E°8¸WÀhÔOÐtx€IÙØÐä
  ¨¸'Ô
B€CØ
€Ü˜U H¨c°8Ô<Øˆ
ä
‡K�Kð	?àˆxÔ4°QÐ7ôô Ô4°e·k±k³mÓ
D€CÙ
Ü�‰ÐkÐpsÐtuÑpvÐwxÐoyð  }Bð  DGð  HIñ  DJô  	KØ�1‰vˆä! %¨Ô2Ü#Ð#r   c                 óv   — t        | «      \  }}|rt        j                  d|d›| |«       |S t        | |||«      S )u¹  Step 2 for a custom ``api_mode: codex_responses`` route â€” a Codex proxy on a generic URL.
    The Codex OAuth table (with the opted-in ``-900k`` bump) answers first: the proxy's own /models
    and the direct-API catalog both advertise the 1.05M direct window that Codex does not honour.
    No live catalog probe â€” the route's key is the proxy's, not a ChatGPT token. Slugs the table
    does not know take the ordinary endpoint probes.zNUsing Codex OAuth context length %s for model %r (codex_responses route at %s)r™   )rÃ  rk   r¥  rï  )rD   r    r   rB  r{  Ú_sources         r   Ú*_resolve_custom_codex_route_context_lengthrò    sO   € ô CÀ5ÓI�L€CˆÙ
Ü�‰ÐdÐilÐmnÐhoÐrwð  zBô  	CØˆ
Ü2°5¸(ÀGÈXÓVÐVr   c                 ó‚  — 	 ddl m}m} ddlm} ddlm}  |«       }|€ ||«      } ||j                  d«      xs i | «      j                  d«      xs i }t        |j                  d«      xs d	«      j                  «       }t        |j                  d
«      xs d	«      j                  «       }	|	rj|rh|j                  «       dk7  rU |||	¬«      }
t        |	|
j                  dd	«      xs d	|
j                  dd	«      xs d	|
j                  d«      xs ||¬«      S y# t        $ r t        j                  dd¬«       Y yw xY w)u¹   Step 0a: MoA virtual provider â€” ``model`` is a preset name, so every probe would miss. Resolve
    the aggregator's real provider+model (references are advisory). None on any failure.r   )Úget_compatible_custom_providersÚload_config)Úresolve_moa_preset)Úresolve_runtime_providerNÚmoaÚ
aggregatorrB  r   rD   )rü  Útarget_modelr    r   )r    r   rB  r�  z/MoA aggregator context-length resolution failedT)Úexc_info)r)   rô  rõ  Úhermes_cli.moa_configrö  Úhermes_cli.runtime_providerr÷  r*   r,   rN   r>   Úget_model_context_lengthr0   rk   rl   )rD   r�  rô  rõ  rö  r÷  r_  ÚaggÚagg_providerÚ	agg_modelÚrts              r   Ú_resolve_moa_context_lengthr  ,  s/  € ðWßRÝ<ÝHÙ“ˆØÐ#Ù>¸vÓFÐÙ  §¡¨EÓ!2Ò!8°b¸%Ó@×DÑDÀ\ÓRÒXÐVXˆÜ˜3Ÿ7™7 :Ó.Ò4°"Ó5×;Ñ;Ó=ˆÜ˜Ÿ™ Ó(Ò.¨BÓ/×5Ñ5Ó7ˆ	Ù™¨,×*<Ñ*<Ó*>À%Ò*GÙ)°LÈyÔYˆBÜ+Ø B§F¡F¨:°rÓ$:Ò$@¸bÈ"Ï&É&ÐQZÐ\^ÓJ_ÒJeÐceØŸ™ 
Ó+Ò;¨|ÐN^ôð ð øô ò WÜ�‰ÐFÐQUˆÕVØðWús   ‚DD Ä D>Ä=D>c                 óN  — |rE| rCt        j                  t        «      5  ddlm}  ||| «      }|�|dkD  r|cddd«       S ddd«       |rD| rBt        j                  t        «      5  ddlm}  || ||¬«      }|r|cddd«       S 	 ddd«       yy# 1 sw Y   ŒPxY w# 1 sw Y   yxY w)u   Steps 0b-0c: config-only overrides (never touch the network). 0b: EXPLICIT model_overrides
    only â€” fill-gap _default entries apply inside lookup_models_dev_context once the catalog has
    missed, so a _default can never preempt custom_providers or live probes. 0c: custom_providers.r   )Ú_override_context_windowN)Ú"get_custom_provider_context_length)rD   r    r�  )r”  r•  r0   Úagent.models_devr  r)   r  )rD   r    rB  r�  r  Úmo_ctxr  Úcp_ctxs           r   Ú_config_override_context_lengthr
  D  sª   € ñ ‘EÜ× Ñ ¤Ó+ñ 	ÝAÙ-¨h¸Ó>ˆFØÐ! f¨q¢jØ÷		÷ 	ñ 	ñ ‘EÜ× Ñ ¤Ó+ñ 	ÝLÙ7¸eÈhÐiyÔzˆFÙØ÷		ñ 	ð ÷	ñ
 ÷!	ð 	ú÷	ð
 ús   žBÁ%BÂBÂB$Úeffective_providerc                 ó.  ‡ ‡‡— |dv r@t        j                  t        «      5  ddlm}  |‰ ‰¬«      }|r|cddd«       S 	 ddd«       ˆˆˆ fd„ˆˆ fd„dœj                  |«      }|�# |«       \  }}}	|r‰r||	k(  rt        ‰ ‰|«       |S |d	v r‰rt        ‰ ‰‰¬«      }|�|S ‰r3t        ‰«      }
|
�d
|
v rt        ‰ ‰‰¬«      nd}|�t        ‰ ‰||«       |S |dk(  rSt        «       j                  ‰ «      xs i j                  d«      }t        |t        «      r|dkD  r|dk(  rt        ‰ «      s|S |rXddlm}  ||‰ «      }|rGt#        ‰ «      rt$        j                  d«      nd}|r!||k  rt&        j)                  d|‰ |d›«       |}|S y# 1 sw Y   �ŒLxY w)zFStep 5: provider-specific sources, tried in order; None when all miss.>   úcopilot-acpúgithub-copilotr4  r   )Úget_copilot_model_contextrŸ  Nc                  ó6   •— t        ‰‰xs d‰ xs d¬«      dz   S )Nr   r  )rÅ  )rÖ  r8  s   €€€r   rf  z8_resolve_provider_aware_context_length.<locals>.<lambda>l  s#   ø€ Ô4°UÀXÂ^ÐQSÐ]dÒ]jÐhjÔkÐnyÑy€ r   c                  ó,   •— t        ‰‰ xs d¬«      dz   S )Nr   r©  )r½  )rÃ  )r   rD   s   €€r   rf  z8_resolve_provider_aware_context_length.<locals>.<lambda>m  s   ø€ Ô OÐPUÐdkÒdqÐoqÔ rÐu~Ñ ~€ r   )r3  r�  >   úcommandcode-anthropicr9  ÚcommandcoderË  r2  r  ró   )Úlookup_models_dev_contextrè   z[Rejecting models.dev context=%s for %r (MiniMax-M3 underreport); using hardcoded default %sr™   )r”  r•  r0   Úhermes_cli.modelsr  r*   r˜  rš  rC  r;  r™  rX  r+   rr  rA  r  r  rE  rI  rk   r¥  )rD   r    r   rB  r  r  r{  Úsourcedr  Ú
persist_onÚinferredÚor_ctxr  Úcatalogs   ```           r   Ú&_resolve_provider_aware_context_lengthr  ^  sà  ú€ ð ÐIÑIÜ× Ñ ¤Ó+ñ 	ÝCÙ+¨E¸7ÔCˆCÙØ÷		ñ 	ð ÷	õ zÜ~ñ÷ 
�cÐ
Óð ð ÐÙ")£)ÑˆˆV�ZÙÙ˜F jÒ0Ü# E¨8°SÔ9ØˆJØÐLÑLÑQYô /¨u°hÈÔPˆØˆ?ØˆJñ Ü+¨HÓ5ˆØJRÐJZÐ^fÐjrÑ^rÔ$ U¨H¸gÕFÐx|ˆØˆ?Ü  ¨°#°xÔ@ØˆJð ˜\Ò)Ü&Ó(×,Ñ,¨UÓ3Ò9°r×>Ñ>Ð?OÓPˆä�fœcÔ" v°¢z¸6ÀUº?ÔOhÐinÔOoØˆMÙÝ>Ù'Ð(:¸EÓBˆÙäCbÐchÔCiÔ-×1Ñ1°,Ô?ÐosˆGÙ˜3 š=Ü—‘ÐyÐ{~ð  AFð  KRð  STð  JUô  WØ�ØˆJØ÷c	ñ 	ús   ¡F
Æ
FÚconfig_context_lengthc                 óL  — t        |t        «      r|dkD  r|S |xs dj                  «       j                  «       dk(  rt	        | |«      }|�|S t        | |||«      }|�|S |r	 t        t        |«      «      j                  }t        | xs d«      j                  «       s"t        j                  dt        d›«       t        S t        | «      } t        | ||¬«      } t!        | |«      }|�|S ddlm}	  |	|«      }
|
r|
j'                  | «      nd}t)        |«      t        u r|dkD  r|S t+        ||«      }t-        |||«      }|r|s|st/        ||«      st1        | |«      nd}|�t3        | |||¬	«      nd}|�|S |rt5        | |«      nd}|�|S |d
k(  s|r1t7        |d«      r%t9        | |xs d|¬	«      }|�|rt;        | ||«       |S t=        |«      rIt?        |«      s>|xs dj                  «       j                  «       dk7  r|rt@        ntB        } || |||«      S |dk(  s|r#tE        |«      dk(  rtG        | |xs d|«      }|r|S |}|r|r|dv rtI        |«      xs |}tK        | ||||«      }|�|S |sQtM        «       }| |v rC||    jO                  dt        «      }|dk(  r#tQ        | «      rt        j                  d|| «       n|S |rtS        |«      rtU        | |||«      nd}|r|S tW        tX        | j                  «       «      }|r|d   S t[        | |«       t        S # t        $ r d}Y �Œ¢w xY w)aö  Context length for a model. Resolution order: 0 config override / MoA aggregator /
    model_overrides / custom_providers / endpoint-scoped; 1 persistent cache (Nous, LM
    Studio, Codex OAuth bypass it) and Bedrock; 2-3 custom endpoints (/models, local
    probe, Ollama); 4 Anthropic /v1/models (API keys only); 5 provider-aware (Copilot,
    Nous, Codex OAuth, GMI, Ollama, OpenRouter live, models.dev); 6 OpenRouter for
    unknown providers; 7 local server; 8 hardcoded defaults; 9 256K fallback.r   r   rø  NuO   No model id provided for context length resolution â€” defaulting to %s tokens.r™   rŽ  rI   rŸ  r;  r:  zhttps://api.novita.ai/openai/v1r�  r-  r,  zhttps://api.anthropic.com>   Úcustomr2  r  ró   znRejecting OpenRouter metadata context=%s for %r (known 32K underreport); falling through to hardcoded defaultsrH   ).r+   rr  rN   r>   r  r
  r   r]   re   rs  r,   rk   r¥  rÊ   rT   rG  rŠ  rM   rJ   rþ  r¼  r·  r–  r�  r¿  rÜ  rí  r   rš  r˜  r*  rI  rò  rï  r   r~  rC  r  rX  r*   rS  rÁ  r¢  ri  rI  rË   )rD   r    r   r  rB  r�  r{  r	  Úendpoint_contextrJ   r@   rÒ  Úis_bedrock_contextÚcodex_router£  Ú	validatedÚresolver  r'  r  r¡  rÂ  s                         r   rþ  rþ  —  sÅ  € ô Ð'¬Ô-Ð2GÈ!Ò2KØ$Ð$ØŠ�B×ÑÓ×%Ñ%Ó'¨5Ò0Ü)¨%Ð1AÓBˆØˆ?ØˆJÜ
)¨%°¸8ÐEUÓ
V€CØ
€Øˆ
ñ ð	ÜÔ,¨XÓ6Ó7×<Ñ<ˆAô
 ˆuŠ{˜Ó×!Ñ!Ô#Ü�‰Ðeô  kCð  DEð  jFô  	HÜ'Ð'Ü" 5Ó)€Eô .¨e¸hÐQYÔZ€Eô 7°u¸hÓGÐØÐ#ØÐõ /Ù" 8Ó,€GÙ9@ˆg×.Ñ.¨uÔ5Àd€GÜˆGƒ}œÑ ¨!¢ØˆÜ,¨X°xÓ@Ðô " (¨HÐ6FÓG€Ká;CÑL^Ñgrô  |Zð  [cð  emô  |nÔ& u¨hÔ7ð  tx€FØ]cÐ]oÔ/°°xÀÐQXÕYÐuy€IØÐØÐñ ?QÔ
)¨%°Ô
:ÐVZ€CØ
€Øˆ
Ø�8Ò¡Ô-BÀ8È_Ô-]Ü.¨u°hÒ6cÐBcÐmtÔuˆØˆ?ÙÜ# E¨8°SÔ9ØˆJô ˜8Ô$Ô-HÈÔ-RÐX`ÒXfÐdf×WmÑWmÓWo×WuÑWuÓWwð  |Jò  XJÙ@KÕ<ÔQxˆÙ�u˜h¨°Ó:Ð:à�;Ò¡8Ô0AÀ(Ó0KÐObÒ0bÜ-¨e°XÒ5\ÐA\Ð^eÓfˆÙØˆJð "ÐÙÑ+Ð/AÐE]Ñ/]Ü5°hÓ?ÒUÐCUÐÜ
0°¸À'È8ÐUgÓ
h€CØ
€Øˆ
ñ Ü'Ó)ˆØ�HÑØ˜e‘_×(Ñ(Ð)9Ô;SÓTˆFØ˜ŠÔ#MÈeÔ#TÜ—‘ð  Mð  OUð  W\õ  ]à�ñ T\Ô`qÐrzÔ`{Ô+¨E°8¸WÀhÔOð  BF€IÙØÐä
Ô4°e·k±k³mÓ
D€CÙ
Ø�1‰vˆä! %¨Ô2Ü#Ð#øôs ò 	Ø‹Hð	ús   Á"L ÌL#Ì"L#c           	   ƒ   ó^   K  — ddl }|j                  t        | |||||¬«      ƒ d{  –—† S 7 Œ­w)z[get_model_context_length on a worker thread (its blocking HTTP would stall the event loop).r   N)r    r   r  rB  r�  )ÚasyncioÚ	to_threadrþ  )rD   r    r   r  rB  r�  r%  s          r   Úget_model_context_length_asyncr'  	  s@   è ø€ ãØ×"Ñ"Ü  %°(ÀGØ3¸hÐYið #ó k÷ kð kð kús   ‚$-¦+§-r«  u,   [á„€-á‡¿âº€-é¿¿ê¥ -ê¥¿ê°€-íž¯ï¤€-ï«¿ï¼€-ï¿¯]Úchc                 ó0   — t         j                  | «      d uS r9   )Ú_CJK_DENSE_REÚ	fullmatch)r(  s    r   Ú_is_cjk_token_dense_charr,  	  s   € Ü×"Ñ" 2Ó&¨dÐ2Ð2r   c                 ó  — | syt        | «      } | j                  «       rt        | «      dz   t        z  S t        j                  d| «      }t        | «      t        |«      z
  }|t        |j                  dd«      «      dz   t        z  z   S )a*  Rough token estimate: CJK/Hangul/Kana codepoints ~1 token each; everything else ceil(UTF-8 bytes/4).
    Ceiling keeps short texts from estimating 0. Runs on every preflight walk, so all-ASCII stays O(1).

    Byte-counting (not chars) is the corrective for non-CJK, non-ASCII text: Cyrillic/Greek/Arabic are 2
    bytes/char so count ~chars/2, matching real BPE cost (~2-3 chars/token) where chars/4 under-counted
    ~2x and let sessions ride the provider ceiling below the compaction threshold. Calibrated vs
    cl100k/o200k/Qwen2.5 (estimate/real): Russian 0.67->1.24, Arabic 0.53->0.96, Hindi 0.34->0.90,
    Greek 0.37->0.68; accented Latin barely moves (French 1.02->1.03). errors="replace": lone surrogates
    (routine in tool output; see message_sanitization) must not turn an estimate into a raise.r   rç  r   r„   r  )r,   ÚisasciirM  ÚCHARS_PER_TOKENr*  rZ  r§  )rÓ  rÆ  Údenses      r   Úestimate_tokens_roughr1  !	  sx   € ñ ØÜˆt‹9€DØ‡|�|„~Ü�D“	˜A‘¤/Ñ1Ð1Ü× Ñ   TÓ*€HÜ�‹Iœ˜H›Ñ%€EØ”S˜Ÿ™¨°)Ó<Ó=ÀÑAÄoÑUÑVÐVr   T©Úcharge_stale_thinkingÚmessagesr3  c                ó`   ‡— ddl m}  |«       Š|st        | «      } t        ˆfd„| D «       «      S )uA  Rough token estimate for a message list (pre-flight only). Images cost the per-image price
    learned from provider usage (``agent.image_token_cost``; flat default before calibration)
    rather than their base64 length. ``charge_stale_thinking=False`` mirrors the tail-budget
    walk (``context_compressor._estimate_msg_budget_tokens``): on non-echo routes stale reasoning
    rides the wire only for the NEWEST assistant turn, so excluding it keeps the compaction TRIGGER
    in the same size class as the walk â€” otherwise reasoning-heavy sessions fire preflight forever.r   )Úcurrent_image_token_costc              3   ó6   •K  — | ]  }t        |‰«      –— Œ y ­wr9   )Ú_estimate_message_tokens_cached)r?   rÚ  Ú
image_costs     €r   rB   z1estimate_messages_tokens_rough.<locals>.<genexpr>A	  s   øè ø€ ÒTÀCÔ.¨s°J×?ÑTùó   ƒ)Úagent.image_token_costr6  Ú"_strip_stale_thinking_for_estimateÚsum)r4  r3  r6  r9  s      @r   Úestimate_messages_tokens_roughr>  5	  s/   ø€ õ @á)Ó+€JÙ Ü5°hÓ?ˆÜÓTÈ8ÔTÓTÐTr   )Ú	reasoningÚreasoning_contentc                 óˆ  ‡ ‡‡— dt         dt        fd„Št        ˆˆ fd„t        t	        ‰ «      dz
  dd«      D «       d«      }t        ‰ «      D ��‡��cg c]Y  \  }Š||k7  rM ‰‰«      rEt        ˆfd„t        D «       «      r-‰j                  «       D ��ci c]  \  }}|t        vsŒ||“Œ c}}n‰‘Œ[ c}}}}S c c}}w c c}}}}w )z½Copy of ``messages`` with stale thinking keys removed (newest kept). Shallow stripped copies
    share the original value objects, so the per-message memo still hits for the stripped shape.r‹  r!   c                 óN   — t        | t        «      xr | j                  d«      dk(  S )NÚroleÚ	assistantrŠ  )r‹  s    r   Ú_is_assistantz9_strip_stale_thinking_for_estimate.<locals>._is_assistantL	  s!   € Ü˜!œTÓ"ÒC q§u¡u¨V£}¸Ñ'CÐCr   c              3   ó:   •K  — | ]  } ‰‰|   «      sŒ|–— Œ y ­wr9   r:   )r?   ÚirE  r4  s     €€r   rB   z5_strip_stale_thinking_for_estimate.<locals>.<genexpr>N	  s   øè ø€ Ò]˜Á-ÐPXÐYZÑP[ÕB\”1Ñ]ùr–  rH   rû   c              3   ó@   •K  — | ]  }‰j                  |«      –— Œ y ­wr9   rý  )r?   rŸ   r‹  s     €r   rB   z5_strip_stale_thinking_for_estimate.<locals>.<genexpr>Q	  s   øè ø€ Ò3dÀ°A·E±E¸!·HÑ3dùrþ   )	r   r   rˆ  ÚrangerM  Ú	enumerater  Ú_STALE_THINKING_ESTIMATE_KEYSr�   )r4  ÚnewestrG  r‹  rŸ   r    rE  s   `  `  @r   r<  r<  I	  s»   ú€ ðDœð D¤ó DäÔ]œe¤C¨£M°AÑ$5°r¸2Ó>Ô]Ð_aÓb€Fô ˜hÓ'÷ò ñ ˆAˆqð �Š;™=¨Ô+´Ó3dÔFcÔ3dÔ0dð Ÿ'™'›)×N‘$�!�Q qÔ0MÒ'MˆˆA‰ÔNØjkñ	lõð ùÛNùõs   ÁA B<
ÂB6Â#B6Â(B<
Â6B<
Ú_MSG_TOKENS_CACHErN  Úpinsc                 óŠ  ‡— | �| du s| du r| S t        | «      }|t        u r‰j                  | «       dt        | «      fS |t        u s|t
        u rd|j                  | fS |t        u r$dt        ˆfd„| j                  «       D «       «      fS |t        u s|t        u r |t        u rdndt        ˆfd	„| D «       «      fS t        d
«      ‚)NTFri  ÚnÚdc              3   óT   •K  — | ]  \  }}t        |‰«      t        |‰«      f–— Œ! y ­wr9   ©Ú_msg_fingerprint)r?   rŸ   r    rN  s      €r   rB   z#_msg_fingerprint.<locals>.<genexpr>r	  s-   øè ø€ ÒlÑVZÐVWÐYZÔ,¨Q°Ó5Ô7GÈÈ4Ó7PÔQÑlùs   ƒ%(ÚlÚtc              3   ó6   •K  — | ]  }t        |‰«      –— Œ y ­wr9   rS  )r?   r    rN  s     €r   rB   z#_msg_fingerprint.<locals>.<genexpr>t	  s   øè ø€ Ò0ZÈqÔ1AÀ!ÀT×1JÑ0Zùr:  zunfingerprintable message value)r¼  r,   ÚappendrL  rr  r’   r   rŠ   Útupler�   rê  rs  )rA   rN  rV  s    ` r   rT  rT  h	  sÁ   ø€ Ø€}˜ ™¨°%©ØˆÜˆU‹€AØŒC�xØ�‰�EÔØ”R˜“YÐÐØŒC�x�1œ‘:Ø�Q—Z‘Z Ð'Ð'ØŒD�yØ”UÓlÐ^c×^iÑ^iÓ^kÔlÓlÐmÐmØŒD�y�Aœ‘JØœD‘y‘ c¬5Ó0ZÐTYÔ0ZÓ+ZÐ[Ð[Ü
Ð6Ó
7Ð7r   rÚ  r9  c                 ó  ‡ — dt         t        t        f   fˆ fd„}	 g }t        ‰ |«      }t        |«       t
        j                  |«      }|�|d   |d   |z  z   S  |«       \  }}|||z  z   }|||ft
        |<   t        t
        «      t        kD  rC	 t
        j                  t        t        t
        «      «      «       t        t
        «      t        kD  rŒC|S # t        $ r  |«       \  }}|||z  z   cY S w xY w# t        t        t        f$ r Y |S w xY w)z¡Text tokens + images x ``image_cost``; the memo holds text and image COUNT so a recalibrated
    per-image price re-prices cached rows without invalidating them.r!   c                  ó2   •— t        ‰ «      t        ‰ d«      fS )NrH   )Ú'_estimate_message_tokens_without_imagesÚ_count_image_tokens©rÚ  s   €r   Ú_computez1_estimate_message_tokens_cached.<locals>._compute{	  s   ø€ Ü6°sÓ;Ô=PÐQTÐVWÓ=XÐXÐXr   rH   rq  )r	   rr  rT  Úhashr0   rM  r*   rM  Ú_MSG_TOKENS_CACHE_MAXr²  rˆ  r—  ÚStopIterationr  ÚRuntimeError)	rÚ  r9  r_  rN  rn   rÓ  Úimagesr£  Útokenss	   `        r   r8  r8  x	  s"  ø€ ðY”eœC¤˜H‘oõ Yð*ØˆÜ˜s DÓ)ˆÜˆSŒ	ô ×"Ñ" 3Ó'€FØÐØ�a‰y˜6 !™9 zÑ1Ñ1Ð1Ù“:�L€Dˆ&Ø�F˜ZÑ'Ñ'€FØ" D¨&Ð1Ô�cÑÜ
ÔÓ
 Ô#8Ò
8ð	Ü×!Ñ!¤$¤tÔ,=Ó'>Ó"?Ô@ô ÔÓ
 Ô#8Ó
8ð
 €Møô ò *Ù“z‰ˆˆfØ�f˜zÑ)Ñ)Ò)ð*ûô œx¬Ð6ò 	ØØ€Mð	ús#   œC Â+C4 ÃC1Ã0C1Ã4DÄDru  Útypesc                 óP   ‡— t        | t        «      rt        ˆfd„| D «       «      S dS )Nc              3   ól   •K  — | ]+  }t        |t        «      sŒ|j                  d «      ‰v sŒ(d–— Œ- y­w)r¼  rH   NrŠ  )r?   Úpartrf  s     €r   rB   z_count_parts.<locals>.<genexpr>“	  s+   øè ø€ Ò[�T¤j°´tÕ&<ÀÇÁÈ&ÓAQÐUZÒAZŒqÑ[ùs   ƒ4™4­4r   )r+   rê  r=  )ru  rf  s    `r   Ú_count_partsrj  ’	  s%   ø€ Ü_iÐjoÔquÔ_vŒ3Ó[˜UÔ[Ó[Ð}Ð|}Ð}r   >   ÚimageÚ	image_urlÚinput_imageÚcost_per_imagec                 ót  — t        | t        «      sy| j                  d«      }t        |t        «      }|t        | j                  d«      dh«      z  }t        |t        «      r1|j                  d«      r |t        |j                  d«      ddh«      z  }|t        | j                  d«      t        «      z  }||z  S )zECount image-like content parts in a message; return their token cost.r   ÚcontentÚ_anthropic_content_blocksrk  Ú_multimodalrl  r2  )r+   rŠ   r*   rj  Ú_IMAGE_PART_TYPES)rÚ  rn  rp  rÄ  s       r   r]  r]  ™	  s£   € ä�cœ4Ô ØØ�g‰g�iÓ €GÜ˜Ô"3Ó4€EØ	Œ\˜#Ÿ'™'Ð"=Ó>ÀÀ	ÓJÑJ€Eä�'œ4Ô  W§[¡[°Ô%?Ø”˜gŸk™k¨)Ó4°wÀÐ6LÓMÑMˆð 
Œ\˜#Ÿ'™' (Ó+Ô->Ó?Ñ?€EØ�>Ñ!Ð!r   r�   c                 óÞ   — t        | t        «      s| S | D ���cg c]?  }t        |t        «      r+|j                  «       D ��ci c]  \  }}||dk(  rdn|“Œ c}}n|‘ŒA c}}}S c c}}w c c}}}w )zþ``codex_reasoning_items`` with ``encrypted_content`` blanked for local token estimation.
    The ciphertext is priced by the provider's own count, never by its bytes (a compaction
    checkpoint alone can be 5M chars, #100611); only real usage prices it.Úencrypted_contentr   )r+   rê  rŠ   r�   )r�   rì  rŸ   r    s       r   Ústrip_opaque_replay_itemsrv  ©	  st   € ô �eœTÔ"Øˆð ÷ð àô R\Ð\`ÔbfÔQgÀÇ
Á
Ã×M¹¸¸1ˆ�1Ð+Ò+‰R°Ñ	2ÔMÐmqÑqôð ùÛMùôs   ™(A(ÁA"ÁA(Á"A(c                 óú  — | j                  d«      }t        |t        «      xr  t        |«      xr | j                  d«      dv }| j                  d«      }t        |t        «      xr t        |j	                  «       «      }i }| j                  «       D �][  \  }}|dv s|t        v s|dk(  r|rŒ|dk(  r	|sŒ#||d<   Œ)|dk(  r|rŒ1|dk(  r_t        |t        «      rO|D �cg c]?  }t        |t        «      r+|j                  d«      t        v r|j                  d«      d	d
œn|‘ŒA c}||<   Œ•|dk(  r7t        |t        «      r'|j                  d«      r|j                  dd«      ||<   ŒÑ|dk(  r`t        |t        «      rP|D �cg c]?  }t        |t        «      r+|j                  d«      t        v r|j                  d«      d	d
œn|‘ŒA c}||<   �Œ6|dk(  rt        |«      ||<   �ŒK|dk(  rd||<   �ŒW|||<   �Œ^ |S c c}w c c}w )u²  Shadow of a message holding only what the provider actually receives.
    * ``api_content`` SUBSTITUTES ``content`` (mirrors ``turn_context.substitute_api_content`` exactly):
      only a non-empty STRING sidecar on a user/assistant row displaces content; substituting any
      other shape would UNDERcount â€” the dangerous direction.
    * Base64 images become a placeholder; ``_count_image_tokens`` charges them flat.
    * ``reasoning`` never ships as-is (request builds pop it after optionally promoting it into
      ``reasoning_content``); counting both inflated estimates up to +53%.
    * Opaque provider blobs (``encrypted_content`` on codex reasoning / compaction items) are
      ciphertext the provider prices by its OWN token count, never by bytes; a native compaction
      checkpoint alone can be 5M chars (#100611). They contribute 0 here: only real usage ever
      prices them, and the usage anchor carries that price forward.Úapi_contentrC  )ÚuserrD  r@  )rq  Úreasoning_detailsr?  rp  r¼  z
[stripped])r¼  rk  rr  Útext_summaryr   r2  Úcodex_reasoning_itemsru  )r*   r+   r,   r   rN   r�   r   rê  rŠ   rs  rv  )	rÚ  ÚsidecarÚsidecar_winsÚ_rcÚdrop_reasoning_dupÚshadowrŸ   r    ri  s	            r   Ú_wire_message_shadowr‚  µ	  s  € ð �g‰g�mÓ$€GÜ˜g¤sÓ+Òj´°W³ÒjÀ#Ç'Á'È&Ã/ÐUjÐBj€LØ
�'‰'Ð%Ó
&€CÜ# C¬Ó-ÒC´$°s·y±y³{Ó2CÐØ€FØ—	‘	“ó  ‰ˆˆ1ØÐBÑBÀaÔKjÑFjÐopÐtÒoñ  EWØØ�ÒÚØ$%��yÒ!Ø�)Š^¡ØØ�)Š^¤
¨1¬dÔ 3ð
 ö	ð ô ˜d¤DÔ)¨d¯h©h°vÓ.>ÔBSÑ.Sð Ÿ™ &Ó)°LÒAàñòˆF�1ŠIð �)Š^¤
¨1¬dÔ 3¸¿¹¸mÔ8LØŸ™˜n¨bÓ1ˆF�1ŠIØ�(Š]œz¨!¬TÔ2ð ö	ð ô ˜d¤DÔ)¨d¯h©h°vÓ.>ÔBSÑ.Sð Ÿ™ &Ó)°LÒAàñòˆF�1‹Ið Ð)Ò)Ü1°!Ó4ˆF�1‹IØÐ%Ò%ØˆF�1‹IàˆF�1‹IðA ðB €Mùò1ùòs   ÃAG3Å<AG8c                 óp   — t        t        t        | t        «      rt	        | «      «      «      S | «      «      S )zAToken estimate for a message shadow with image payloads stripped.)r1  r,   r+   rŠ   r‚  r^  s    r   r\  r\  ê	  s.   € ä ¤Ä*ÈSÔRVÔBWÔ%9¸#Ó%>Ó!aÓbÐbÐ]`Ó!aÓbÐbr   )Úsystem_promptÚtoolsr3  r„  r…  c                ó‚   — |rt        |«      nd}| r||rt        | «      nt        | d¬«      z  }|r|t        |«      z  }|S )u  Rough token estimate for a full request: system prompt + messages + tool schemas (50+ tools
    add 20-30K on their own). ``charge_stale_thinking`` is forwarded â€” pass False when the route
    provably strips stale thinking (``message_sanitization.stale_thinking_reaches_wire``).r   Fr2  )r1  r>  Ú_estimate_tools_tokens_rough)r4  r„  r…  r3  Útotals        r   Úestimate_request_tokens_roughr‰  ï	  sY   € ñ 5BÔ! -Ô0Àq€EÙàÑ=RÔ/°Ô9ÔXvÐwð  X]ô  Y^ñ  	^ˆÙØÔ-¨eÓ4Ñ4ˆØ€Lr   Ú_TOOLS_TOKENS_CACHEé   Útoolc                 óú   — t        | t        «      sy| j                  d«      }t        |t        «      r|j                  d«      nd }t        |t        «      r|n| j                  d«      }t        |t        «      r|S dS )Nr   Úfunctionr   )r+   rŠ   r*   r,   )rŒ  Úfnr   s      r   Ú_tool_name_for_cacher�  
  sb   € Ü�dœDÔ!ØØ	�‰�*Ó	€BÜ'¨¬DÔ1ˆ2�6‰6�&Œ>°t€DÜ˜d¤CÔ(‰4¨d¯h©h°vÓ.>€DÜ˜d¤CÔ(ˆ4Ð0¨bÐ0r   c           	      ó   — | syt        | «      }t        | «      t        | d   «      t        | d   «      f}t        j	                  |«      }|�|d d |k(  r|d   S d}| D ]¯  }t        |t        «      sŒ|j	                  d«      }t        |t        «      r|n|}|j	                  d«      xs i }|t        d„ |j	                  d«      xs d|j	                  d	«      xs dfD «       «      z  }	 |t        t        j                  |d
d¬«      «      z  }Œ± |dz   dz  }	t        t        «      t        k\  r,t        j                  t        t        t        «      «      d «       g |¢|	‘­t        |<   |	S # t        $ r |t        t        |«      «      z  }Y �Œ/w xY w)Nr   rû   rç  rŽ  rn  c              3   óT   K  — | ]   }t        |t        «      sŒt        |«      –— Œ" y ­wr9   )r+   r,   rM  r  s     r   rB   z/_estimate_tools_tokens_rough.<locals>.<genexpr>
  s    è ø€ Òw aÔdnÐopÔruÕdvœ3˜qŸ6Ñwùs   ‚(˜(r   r   ÚdescriptionFr˜   )Úensure_asciirœ   r«  )rL  rM  r�  rŠ  r*   r+   rŠ   r=  rˆ   Údumpsr0   r,   Ú_TOOLS_TOKENS_CACHE_MAXr²  rˆ  r—  )
r…  rn   Ú	signaturer£  Útotal_charsrŒ  r�  rg  rj  re  s
             r   r‡  r‡  
  s‡  € ÙØÜ
ˆU‹)€CÜ�U“Ô1°%¸±(Ó;Ô=QÐRWÐXZÑR[Ó=\Ð]€IÜ ×$Ñ$ SÓ)€FØÐ˜f R a˜j¨IÒ5Ø�a‰yÐà€KØò 
,ˆÜ˜$¤Ô%ØØ�X‰X�jÓ!ˆÜ˜r¤4Ô(‰b¨dˆØ—‘˜Ó&Ò,¨"ˆØ”sÑw¨C¯G©G°F«OÒ,A¸rÀ3Ç7Á7È=ÓCYÒC_Ð]_Ð+`ÔwÓwÑwˆð	,Øœ3œtŸz™z¨&¸uÐQ[Ô\Ó]Ñ]‰Kð
,ð ˜A‰o !Ñ#€FÜ
ÔÓÔ#:Ò:Ü×Ñ¤¤TÔ*=Ó%>Ó ?ÀÔFØ3 Ð3¨FÑ3Ô˜ÑØ€Møô ò 	,Øœ3œs 6›{Ó+Ñ+‹Kð	,ús   Ã)$E)Å) FÆF)r   )rG   )r   r   )rÖ  r×  )F)r   Fr9   )rv  )r   r   Nr   N(  Ú__doc__r”  r¥  r·  rˆ   Úloggingr-   r[  ri   Úpathlibr   Útypingr   r   r   r   r   r	   r
   Úurllib.parser   r¡  r   Úutilsr   r   r   r   r€   r   r   Úagent.message_metadatar   Ú	getLoggerr   rk   r   r,   r   r   r6   rM   r7   r;   r0   Ú	frozensetrC   Ú__annotations__ÚcompileÚ
IGNORECASErO   ÚIPv4Networkr½  rT   rU   rV   r’   rP  rW   rX   r¾   rÛ  rÜ  rY   rY  rm   rZ   r_   rg   ro   rr   ÚBaseExceptionrv   ru   rª   r�   r�   r”   r¢   r¥   r«   r­   r¯   r´   r¶   r¸   rº   r¿   rÁ   rÌ  rÊ   ÚsetrÅ   rË   rœ  r2  rÌ   rÞ  rÍ   rI  r  r  r  r  r  r   rZ  rµ  r¶  r]   Úobjectr'  r*  r=  Ú_ppÚget_hostnameÚ_hostr   rC  rG  rI  rO  rT  rX  Újoinrÿ  r\  rY  r_  rr  ri  r|  r‰  rŠ  r�  rê  r–  r™  r�  r¢  r¨  rÁ  rR  ræ  ré  rð  r÷  r  r  r  r  r  r  rA  rF  rX  r\  rb  rf  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é  rê  rè  r  r  r  r   r%  r.  r3  r;  r7  rA  rE  rJ  rO  rQ  rS  r   rX  r^  rb  rk  rV  r^  r~  r€  r�  r‚  r¸  r‰  r‹  rŠ  r‡  r„  rŒ  rŽ  r�  r’  r•  rš  r›  rœ  r¯  rž  ÚCODEX_NEWEST_CLIENT_VERSIONÚCODEX_UNGATED_CLIENT_VERSIONr   r¢  rª  r³  rÃ  rÖ  rÜ  rà  r·  rí  rï  rò  r  r
  r  rþ  r'  r/  r*  r,  r1  r>  rK  r<  rM  ra  rT  r8  rj  rs  r]  rv  r‚  r\  r‰  rŠ  r–  r�  r‡  r:   r   r   ú<module>r¯     s"  ðòó Û Û Û Û Û 	Û 	Û Ý ß L× LÑ LÝ !ã áÛç `Ó `ç KÝ Bà	ˆ×	Ñ	˜8Ó	$€ò!ðK�có Kò sð °D¸3±Jó ð.Ý;ñ
 &/ñ /á"Ó$ô/ó &Ð �I˜c‘Nó ð
 !�b—j‘jÐ!iÐkm×kxÑkxÓyÐ ð )�9×(Ñ(¨Ó9Ð ð #ð ¨#ó ð  46Ð �t˜C  c¨3 h¡Ð/Ñ0Ó 5Ø$%Ð ˜EÓ %ØÐ ð TVÐ   U¨3°¨8¡_°d¸3ÀÀSÈ#ÀXÁÐ;NÑ6OÐ%OÑ PÓ UØDFÐ # T¨%°°S°©/¸5Ð*@Ñ%AÓ FØÐ ð %Ð ð ',Ð #Ø/1Ð ˜D  e Ñ,Ó 1ð #'Ð Ø.0Ð ˜4  U 
Ñ+Ó 0òW˜cð W¨3ó Wð ð ¨°#©ó ðE¨ð E°ó Eð 3ð ¨4ó ð, -ð ,¸3ð ,À4ó ,ð˜]ð ¨tó ð !&Ð ð.�cð .˜dó .ð
˜$ð  4¨¨S¨¡>ó ð
˜ð 
 3ð 
¨Uð 
¸sð 
Èsð 
ÐW_Ð`cÑWdó 
ð }Bò 7˜ð 7 3ð 7¨sð 7¸ð 7È3ð 7Ð[^ð 7Ðfið 7Ðuyð 7ð  GKó 7ð5 dó 5ðI ð I¨#ð I°(¸3±-ó Ið
h ð h¨#ð h°cð h¸dó hð
9¨ó 9ð
°¸±ó ð¨¨c°4¸¸S¸±>Ð.AÑ)Bó ðS¨$¨s°D¸¸c¸±NÐ/BÑ*Cð SÈó Sð7¨4ó 7ð
8¨ð 8°¸$¸sÀDÈÈcÈÁNÐ?RÑ:SÑ1Tó 8ðc¨ð c°T¸#¸tÀCÈÀH¹~Ð:MÑ5Nð cÐSWó cò HÐ Ø.¨qÑ1Ð Ù›Ð �#Ó ð

¨ð 

¸ð 

Àó 

ð  Ð ð  $Ð Ø-/Ð ˜˜U E˜\Ñ*Ó /ð &+Ð "Ø35Ð ˜d 5¨% <Ñ0Ó 5ðIð �gðIð  .¨wðIð 9HÈðIð SdÐelðIð �wð	Ið !2°7ð	Ið =NÈwð	Ið YjÐkrð	Ið
 �wðIð
 !4°WðIð
 ?PÐQXðIð
 [nÐovðIð ˆfðIð �7ðIð �ðIð (¨ðIð 3?ÀñIð �GðIð -¨gðIð 8EÀgðIð PYÐZaðIð �FðIð +¨FðIð 5>¸wðIð ˜6ðIð $2°6ðIð <CÀFðIð ˆwðIð   ðIð" ˆgð#Ið$ ˆvð%Ið$   ð%Ið$ *7¸ð%Ið$ AJÈ6ò%Ið$ T[Ð\`ð%Ið. �yð/Ið. #8¸ð/Ið. EXÐYbð/Ið. etÐu~ð/Ið0 ˜ð1Ið0 %5°ið1Ið0 BLÈVð1Ið8 ˆVð9Ið8 & yð9Ið8 3?À	ð9Ið8 LUÐV_ð9Ið> �9ð?Ið> .¨yð?Ið> ;IÈ'ð?Ið> TbÐcjð?Ið@ ˜òAIð@ "/°ðAIð@ 9DÀVðAIð@ NTÐU[ðAIðD �'ðEIðD % fðEIðN ˆyðOIðN *¨9ðOIðN 7FÀyðOIðN S_Ð`iðOIðP ˜9ðQIðP '9¸)ðQIðP FVÐW`ðQIðR ˆyðSIðR )¨'ðSIðT ˆwðUIðT & vðUIðT 0>¸vòUIðT HOÐPWðUIðV �VðWIðV '¨ðWIðV 2<¸VðWIðV FOÐPWðWIðV Z_Ð`fðWIðb �VðcIðb 1°&ðcIðb ;GÈðcIðb QaÐbhðcIðd �TðeIðd )¨'ðeIðd 4?ÀðeIðf �ðgIðf # FðgIðf -7¸ðgIðf BJÈ6ògIðh ˆfðiIðh  ðiIðh )/°ðiIðl ˆyðmIðl ! &ðmIðr �6ðsIðr (¨ðsIðr 2>¸uðsIðr GSÐTYðsIðr \dÐekðsIðv �9ðwIðv ,¨VðwIðv 6;¸FðwIð~ �9ðIð~ )¨)ðIð~ 6CÀFðIð@ ˜iòAIð@ *4°VðAIðB �FðCIðB ,¨VðCIðB 6?ÀðCIðB ISÐTZðCIðF ˜fðGIðF '=¸fðGIðF GbÐchðGIðH ˜FðIIðH %;¸FðIIðH EbÐciðIIðJ ˜fðKIðJ 'AÀ&ðKIðL  ðMIðL *9¸'ðMIðL DUÐV]ðMIðN �7ñOIðN .5À7Ð\bÐu{ØòQIÐ ð\ !mÐ ðc¨#ð c°$ó cð &˜2Ÿ:™:Ð&VÓWÐ ð6¨#ð 6°$ó 6ð>˜Sð > Tó >ðÐ ð TÐ Ø;€àZÐ ð0 #ð 0¨#ó 0òA˜6ð A¨4°°S°©>ó AðW #ð W¨$ó Wð$Ø�hð$Ø -¨xð$Ø9LÈkð$à�ð$à)¨5ð$ð �}ð$ð '8Ð9Ið$ð LZÐ[hð$ð �ið	$ð "3°Ið	$ð @NÈwð	$ð YfÐgpð	$ð
 ˜ið$ð
 *GÈ	ð$ð
 TdÐeqð$ð �\ð$ð $GÈñ$ñ %¡fð$ñ /AÀ*ð$ñ ™Yð$ñ )=¹ið$ñ J\Ñ]fð$ñ $¡Yð$ñ ™ð$ñ &3±Mð$ñ DNÉuð$ñ ¡ð$ñ +?Áð$ñ K[Ñ\dð$ñ ™5ð$ñ #2±8ð$ñ Ñ 2ð$ñ 5RÑSfð$ñ ‘.ñ$Ð �$�s˜C�x‘.ô ð$	ÙÓ ò /ˆØ× Ñ Ó"ˆÚ�UÐ"2Ò2Ø&)§h¡hÐ˜UÒ#ñ/ð	 sð 	¨x¸©}ô 	ð 57ò$Øð$Øñ$Ø.1ð$àô$ðN:¨#ð :°$ô :ð Cð ¨Cô ðI˜3ð I 3ô Iñ "-Ð Ø&˜BŸJ™JÙ‰C�H‰H‘S˜Ÿ™Ð$BÓCÓDÐEÑEeÐfóhÐ ð
h˜cñ 
h°ð 
h¸ô 
hñ˜d 3¨ 8™nñ ¸3ð À8ÈEÐRUÐWZÐRZÉOÑC\ô ð ^bó ˜t C¨ H™~ñ ¸dñ ÈXÐVYÉ]ð ÐfnÐorÑfsô ð2 ‘i¡Ð.Ó0PÐR[Ð\Ù¡% Ñ+HÐ*IÈ7ÐSðÐ ð^¨3ð ^¸#ð ^À(È3Á-ô ^ð L¨Sñ L¸Cð LÀDô Lñ˜cð ¨Sñ ÀDÈ4ÁKð ÐTXô ð2 ð 2¨sñ 2¸ñ 2Èð 2ÐPTô 2ð5¨Sð 5¸Cñ 5Èð 5ÐQUô 5ð sð °cð ÀCñ ÐSVð Ð[cÐdgÑ[hô ò°#ð Àñ Ècð Ð\_ð Ðilô ð"N ð N¨ô NñDW˜Cð W Cô Wò7 sð 7°Sð 7À(È3Á-ô 7ðz0˜cô 0ò< #ñ <°ñ <ÀSð <ÐZbÐcfÑZgô <ñ  S¨# X¡ñ °e¸CÁ¸H±oð È(ÐSVÉ-ô ñA¨$¨s°C¨x©.ð A¸XÀc¹]ô Añ	P°°S¸#°X±ð 	PÀ8ÈCÁ=ô 	Pñ ¡UÁ5Ø°iòÐ ñ Ð ÙJÐ ñ D¨¨c¨¡Nñ ¸#ð À$ÀsÈCÀxÁ.ô ñ"˜d 3¨ 8™nð °°c¸3°h±ô ðB;˜d 3¨¨S°#¨X©Ð#6Ñ7ñ ;À3ñ ;ÈtÐTWÐY\ÐT\É~ð ;Ðbfô ;ó.¨ð .¸¸cÀ4ÈÈSÈÁ>Ð>QÑ9Rô .ðba  c¨3 h¡ñ a¸3ñ aÐPXÐY\ÑP]ð aÐbfÐgjÐloÐgoÑbpô að D¨¨c¨¡Nð °xÀ±}ô ð¨ñ °d¸3À¸8±nð ÈÈcÐSWÐX[Ð]`ÐX`ÑSaÐNaÑIbô ð":  c¨4°°S°©>Ð&9Ñ!:ñ :Èsñ :Ð]aÐbeÐgjÐbjÑ]kð :Ðx|ô :ð@e 3ð e°ð e¸EÀ#ÀsÀ(¹Oô eñ¨¨c°3¨h©ð ÀÀSÈ$ÈsÐTWÈxÉ.ÐEXÑ@Yð Ð^bÐcfÐhlÐmpÐruÐmuÑhvÐcvÑ^wô ñ 4¨¨S¨¡>ð °d¸3ÀÀSÈ#ÀXÁÐ;NÑ6Oô ò<3¨Cð <3¸#ñ <3ÐSWð <3ÐdhÐilÐnrÐsvÐx{Ðs{Ñn|Ði|Ñd}ô <3ò~	G¨Cð 	G¸3ð 	GÈð 	GÐV^Ð_bÑVcô 	Gð; ô ;ð dô ð&G˜T # s (™^ô Gò
;  S¨# X¡ñ ;À4È$Á;ð ;ÐZ^ô ;ð5˜cð 5¨Sð 5°Sô 5ð
 RTó C˜sð C¨cñ C¸3ñ CÈ3ð CÐX\ô Cò85¨ð 5°sñ 5ÀCñ 5ÐSVð 5Ð`dô 5ð W\ó  Sð °Cñ Ètð Ð`hÐilÑ`mô ð(W¨Sð W¸Cð WÀDô WñDW¨ð W°¸±ô Wñ
¨cð °h¸s±mô ñ6h°cñ hÐSVð hÐ[cÐdgÑ[hô hð "�r—z‘zñ9óÐ ñ1¨#ð 1°(¸3±-ô 1ñB¸ð BÀÈÁô BñPÐ ñÐ ñ	!Ð ñU¨#ð U°(¸5ÀÀcÀ¹?Ñ2Kô UñB˜Cñ B¨ð B°4ô Bñ 3ð ¨4ô ñ(t Cñ t°sð t¸tô tñ

Ðqvô 
˜Sð 
¨3ñ 
¸Cñ 
È%ñ 
Ðjnð 
ð  |Dð  EIð  JMð  ORð  JRñ  ESñ  |Tô 
ð ð ¨cð °dô ò ð ¨sð ¸Sð È(ÐSVÉ-ô ò ¨ð °sð ÀSð ÐRZÐ[_ÑR`ô ñ$
 ñ 
¨x¸¸HÀS¹MÐ8IÑ/Jð 
ÈxÐX[É}ô 
òn #ð n°ð n¸sð nÈHÐUXÉMô nòc¨3ð c¸#ð cÈð cÐU]Ð^aÑUbô cð; Sð ;¨Tô ;ð)¨3ð )°4ô )ñ $ó 	%ó 	Ð ðK¨#ñ K°sð K¸tô Kð@¨ð @°ô @ðS°cð S¸dô Sò
d sð d°cð dÀCð dÐQYÐZ]ÑQ^ô dð
M˜ð M ¨#¡ô Mñ	¨Cð 	¸ð 	ÀÈÁô 	ñ¨#ð °cð ¸hÀs¹mô ñ"°Cð Àð ÈÐQTÉô ò* °ð  ¸sð  ÈSð  ÐZbÐcfÑZgô  ðF# Cð #¨Cô #ð
¨3ð ¸#ð Èð ÐPXÐY\ÑP]ô ð41Ø‘7ð1Ø'©ð1Ø2?Áð1ØJVÑX_ð1á™ð1á"6¹ð1áAPÑRYð1ð ˜7ð1ñ %4±Wð1ð ?MÉgð1ð ‘7ð	1ð ,©Wð	1ð 7EÁgð	1ñ PjÑkrð	1ð
 ‰wð1ð
 "¡7ð1ñ
 -6±wð1ð
 AHÉñ1Ð ˜t C¨ H™~ô ñ  ¡W¹WÑT[òCÐ /°°c¸3°h±ô ñ ±GÙò@Ð ,¨d°3¸°8©nô ñ %,Ð !Ù&Ð ñ xÐ Ù&Ð'zÐ)CÐ'zÀYÐ'zÑPjÐ'zÐlyÐ'zÓ{Ð Ø$˜"Ÿ*™*Ñ%;Ó<Ð ð<˜H S™Mð <¨cô <ð˜h s™mð °ô ðK˜x¨™}ð K°¸#±ô Kð2 H¨S¡Mð 2°dô 2ð
f¨h°s©mð fÀô fñ*¨#ð *°$ô *ñ
_¨Sð _°X¸c±]ô _ð GIÐ ˜D  e¨D°°c°©N¸EÐ,AÑ&BÐ!BÑCÔ Hð =?Ð   S¨$¨s°C¨x©.Ð%8Ñ 9Ô >Ø!%Ð ñ !OÐ Ù&Ð Ù&Ð Ù!ò "à)Ð+GÐHô"ó Ð ñ X¨s¨e°S¨jÑ%9ð ¸eÀDÈÁIÈxÐX[É}ÐD\Ñ>]ô ñ"I°ð I¸ô Iñ
$Àð $ÈÈtÐTWÐY\ÐT\É~Ð_cÐOcÑIdô $òNK¸3ñ KÈcð KÐ[`ÐaiÐjmÑanÐpsÐasÑ[tô KòB¨ð °sð È#ð ÐW\Ð]eÐfiÑ]jÐloÐ]oÑWpô ðD _aó ¨3ð ¸#ñ Àsð ÐX[ð ÐemÐnqÑerô ðD/¨ð /°$ô /ò #ñ °ð ¸dô ð":¨3ð ":¸#ð ":À(È3Á-ô ":ðJ$°3ð $À#ð $ÐPSñ $Ð_bð $Ðgjô $ð@
W°cð 
WÀSð 
WÐSVñ 
WÐbeð 
WÐjmô 
Wð sñ ¸dÀT¹kð ÈhÐWZÉmô ð0¨3ð ¸#ñ Èñ Ð`dÐgkÑ`kð ÐpxÐy|Ñp}ô ð46°#ð 6Àð 6Èsñ 6Ð^añ 6Ðwzð 6ð  @Hð  ILñ  @Mô 6ðt \`Ø8<òr$Øðr$Øðr$Ø-0ñr$ØNQÐTXÉjñr$àñr$à*.°©+ðr$ð 	ôr$òjk°ð k¸sð kÐRUñ kÐsvÐy}Ñs}ñ kð  QTñ kð  mqð  txñ  mxð kð  DGô kñ €à�—
‘
ÑmÓn€ñ3 ð 3¨ô 3ñW ð W¨ô Wñ( eiô U¨T°$°s¸C°x±.Ñ-Añ UÐ]að UÐmpô Uñ" !CÐ ñ
°°d¸3À¸8±nÑ1Eð 
È$ÈtÐTWÐY\ÐT\É~ÑJ^ô 
ð6 79Ð �4˜˜U 4¨¨c >Ñ2Ð2Ñ3Ô 8ÙÐ ð8˜Cñ 8 tð 8°õ 8ñ ¨ñ ¸#ð À#õ ñ4~˜ñ ~ Cð ~¨Cõ ~ñ ÓCÓDÑ ñ"˜T # s (™^ñ "¸Sð "ÀSõ "ñ 	 Sð 	¨Sõ 	ñ2˜d 3¨ 8™nð 2°°c¸3°h±õ 2ñjc°°c¸3°h±ð cÀCõ cð =?Ðhlñ  MQôØ�4˜˜S˜‘>Ñ"ñØ69ñØGOÐPTÐUYÐZ]Ð_bÐZbÑUcÑPdÑGeñð FJðàõð" =?Ñ �T˜#˜u S¨#¨s°CÐ%7Ñ8Ð8Ñ9Ô >ÙÑ ñ1˜sð 1 sõ 1ñ¨¨T°#°s°(©^Ñ(<ð Àö øðIN ò õðûðJ ò 	Úð	ús0   Ây' Ó)y6 Ôy6 Ôy6 ù'y3ù2y3ù6y?ù>y?