Ë
    âß²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m	Z	 ddl
mZmZ ddlmZ ddlmZ ddlmZ ddlmZmZ  ej.                  e«      Zd	ZdZeeeee   f      ed
<    ej@                  «       Z!dZ"dZ# G d„ d«      Z$i Z%eee$f   ed<   defd„Z&defd„Z'defd„Z(dededefd„Z)dedeeeee   f      fd„Z*dee	   fd„Z+deeee   f   ddfd„Z,de-eeeee   f      e.f   fd„Z/dedeeeee   f      fd„Z0ddddœd ed!ed"e.dee   fd#„Z1deeeee   f      fd$„Z2d5d%„Z3 G d&„ d'e«      Z4 e4d(d)d*d+d,d-d. e'«       d d/d0e› �id1d2d3¬4«      Z5 ee5«       y)6a‘  Ramp Router (router.com) provider profile: Responses-only LLM gateway (verified live).

``api_mode="codex_responses"`` + the ``api.router.com`` host mandate in ``hermes_cli/providers.py``
keep every path on the native wire. The catalog is account-scoped, so no ``fallback_models``
(picker uses ``fetch_models()``). Router 400s on ``reasoning.effort`` levels outside a model's
published vocabulary and on any reasoning field for non-reasoning models, so the efforts map
from ``GET /v1/models`` is cached (memory + disk mirror, background warmer; never HTTP on the
request hot path) and fed to the codex transport's clamp via ``supported_reasoning_efforts``.
é    N)ÚPath)ÚAnyÚOptional)ÚEFFORT_LADDER)Ú__version__)Úregister_provider)ÚProviderProfileÚ_profile_user_agentzhttps://api.router.com/v1Ú_efforts_cacheFc                   ó   — e Zd ZdZdZdd„Zy)Ú_CacheStatezUEfforts cache + once-only flags for one Hermes home (same names as the module slots).©r   Ú_warm_startedÚ_disk_checkedNc                 ó.   — d | _         d| _        d| _        y )NFr   )Úselfs    úL/home/ubuntu/.hermes/hermes-agent/plugins/model-providers/router/__init__.pyÚ__init__z_CacheState.__init__+   s   € Ø>BˆÔØ"ˆÔØ"ˆÕó    ©ÚreturnN)Ú__name__Ú
__module__Ú__qualname__Ú__doc__Ú	__slots__r   © r   r   r   r   &   s   „ Ù_àD€Iô#r   r   Ú_state_by_homer   c                  óÌ   — ddl m} m}  | «       €t        j                  t
           S t        5  t        j                   |«       t        «       «      cddd«       S # 1 sw Y   yxY w)z¨Holder of ``_efforts_cache``/``_warm_started``/``_disk_checked``: this module when unscoped
    (tests monkeypatch those slots), else the active home's ``_CacheState``.r   ©Úget_hermes_home_overrideÚhermes_home_keyN)
Úhermes_constantsr!   r"   ÚsysÚmodulesr   Ú_efforts_lockr   Ú
setdefaultr   r    s     r   Ú_stater(   7   sQ   € ÷ KáÓ!Ð)Ü�{‰{œ8Ñ$Ð$Ü	ñ KÜ×(Ñ(©Ó):¼K»MÓJ÷K÷ Kò Kús   ­#AÁA#c                  ó(  — 	 ddl m}  t        d| t        j
                  j                  f«      D ];  }	 t         |d«      xs d«      j                  «       j                  d«      }|sŒ9|c S  t        S # t        $ r d} Y Œww xY w# t        $ r d}Y Œ,w xY w)zXRouter base URL: profile ``.env`` first (scope-aware), plain os.environ as the fallback.r   ©Úget_env_value_prefer_dotenvNÚRAMP_ROUTER_BASE_URLÚ ú/)Úhermes_cli.configr+   Ú	ExceptionÚfilterÚosÚenvironÚgetÚstrÚstripÚrstripÚROUTER_DEFAULT_BASE_URL)Úprefer_dotenvÚresolveÚvalues      r   Ú	_base_urlr<   B   sš   € ðÝRô ˜$ ´·
±
·±Ð ?Ó@ò ˆð	Ü™Ð 6Ó7Ò=¸2Ó>×DÑDÓF×MÑMÈcÓRˆEò ØŠLðô #Ð"øô ò ØŠðûô
 ò 	ØŠEð	ús"   ‚A2 ²2BÁ2B Á?B ÂBÂBc                  ó  — 	 ddl m}  t        d| t        j
                  j                  f«      D ]5  }dD ].  }	 t         ||«      xs d«      j                  «       }|sŒ*|c c S  Œ7 y# t        $ r d} Y Œlw xY w# t        $ r d}Y Œ+w xY w)z“Router key (documented var, then alias), preferring dotenv; plain os.environ
    is the fallback when the dotenv resolver is unavailable or raises.r   r*   N)ÚRAMP_ROUTER_API_KEYÚROUTER_API_KEYr-   )	r/   r+   r0   r1   r2   r3   r4   r5   r6   )r9   r:   Úvarr;   s       r   Ú_resolve_api_keyrA   R   s™   € ðÝRô ˜$ ´·
±
·±Ð ?Ó@ò ˆØ<ò 	ˆCðÜ™G C›LÒ.¨BÓ/×5Ñ5Ó7�ò Ø”ñ	ðð øô ò ØŠðûô ò Ø’ðús"   ‚A' ·#A8Á'A5Á4A5Á8BÂBÚobjÚkeysc                 óZ   — |D ]%  }t        | t        «      r| j                  |«      nd} Œ' | S )zENested dict lookup; None as soon as a level is missing or not a dict.N)Ú
isinstanceÚdictr4   )rB   rC   Úkeys      r   Ú_digrH   d   s.   € àò >ˆÜ(¨¬dÔ3ˆc�g‰g�cŒl¸‰ð>à€Jr   Úitemsc           	      óà  — t        | t        «      syi }| D �]<  }t        |t        «      r,t        |j	                  d«      xs d«      j                  «       nd}t        |ddd«      }|rt        |t        «      sŒc|j	                  d«      du rg ||<   Œ||j	                  d	«      xs g D �cg c]?  }t        |t        «      sŒt        |j	                  d
«      xs d«      j                  «       ‘ŒA }}|D �cg c]  }|sŒ|‘Œ	 }}|D �	cg c]  }	|	t        vsŒ|	‘Œ }
}	|
r/t        j                  d||
«       |D �	cg c]  }	|	t        v sŒ|	‘Œ }}	|s�Œ8|||<   �Œ? |xs dS c c}w c c}w c c}	w c c}	w )a[  Parse a ``/v1/models`` ``data`` array into the efforts map (None if unusable).

    Ladder-unknown levels are dropped: clamp_effort ignores them, so an all-unknown
    vocabulary would pass the effort through unclamped to a Router 400. ``supported=True``
    with no recognized level leaves the model out (unknown -> transport default clamp).
    NÚidr-   ÚrouterÚcapabilitiesÚ	reasoningÚ	supportedFÚeffortsr;   z›router: model %s publishes unrecognized reasoning effort level(s) %s; ignoring them (update agent/reasoning_effort EFFORT_LADDER to adopt new vendor tiers))
rE   ÚlistrF   r5   r4   r6   rH   r   ÚloggerÚinfo)rI   Úefforts_by_idÚitemÚmidrN   ÚeÚvaluesÚvÚlevelsÚlevelÚunknowns              r   Ú_parse_effortsr]   k   sh  € ô �eœTÔ"ØØ*,€MØó (ˆÜ3=¸dÄDÔ3IŒc�$—(‘(˜4“.Ò& BÓ'×-Ñ-Ô/ÈrˆÜ˜˜x¨¸ÓEˆ	Ùœ* Y´Ô5ØØ�=‰=˜Ó%¨Ñ.Ø!#ˆM˜#ÑØØ=F¿]¹]È9Ó=UÒ=[ÐY[Ös¸Ô_iÐjkÔmqÕ_r”#�a—e‘e˜G“nÒ*¨Ó+×1Ñ1Õ3ÐsˆÐsØ#Ö)˜¢q’!Ð)ˆÐ)Ø&,ÖK˜U°¼]Ò0J’5ÐKˆÐKÙÜ�K‰KðZØ[^Ð`gôð *0ÖJ °5¼MÒ3I’eÐJˆFÐJÛØ!'ˆM˜#Óð%(ð& Ò ˜DÐ ùò tùÚ)ùÚKùò Ks0   Â)EÂ?.EÃ3E!Ã;E!ÄE&ÄE&Ä6E+ÅE+c                  óH   — 	 ddl m}   | «       dz  dz  S # t        $ r Y y w xY w)Nr   ©Úget_hermes_homeÚcachezrouter_catalog.json)r#   r`   r0   r_   s    r   Ú
_disk_pathrb   ‹   s0   € ðÝ4ÙÓ  7Ñ*Ð-BÑBÐBøÜò Ùðús   ‚ •	! !rT   c                 ól  — t        «       }|€y 	 |j                  j                  dd¬«       |j                  d«      }|j	                  t        j                  t        j                  «       | dœ«      d¬«       |j                  |«       y # t        $ r }t        j                  d|«       Y d }~y d }~ww xY w)NT)ÚparentsÚexist_okz.tmp)ÚtsrP   úutf-8©Úencodingz)router: caps disk mirror write failed: %s)rb   ÚparentÚmkdirÚwith_suffixÚ
write_textÚjsonÚdumpsÚtimeÚreplacer0   rR   Údebug)rT   ÚpathÚtmpÚexcs       r   Ú
_save_diskrv   “   s“   € Ü‹<€DØ€|ØðGØ�‰×Ñ $°ÐÔ6Ø×Ñ˜vÓ&ˆØ�‰”t—z‘z¬¯©«ÀÑ"OÓPÐ[bˆÔcØ�‰�DÕøÜò GÜ�‰Ð@À#×FÑFûðGús   �A:B
 Â
	B3ÂB.Â.B3c                  óf  — t        «       } | €y	 t        j                  | j                  d¬«      «      }|j	                  d«      }t        |t        «      r|sy|j                  «       D ���ci c]9  \  }}t        |t        «      sŒt        |«      |D �cg c]  }t        |«      ‘Œ c}“Œ; }}}}	 t        dt        j                  «       t        |j	                  d«      xs d«      z
  «      }|xs d|fS c c}w c c}}}w # t        t        f$ r t        t        «      }Y Œ4w xY w# t         $ r Y yw xY w)	zUDisk mirror -> (efforts map or None, age in seconds; TTL when ``ts`` is unparseable).N)Nç        rg   rh   rP   rx   rf   r   )rb   rn   ÚloadsÚ	read_textr4   rE   rF   rI   rQ   r5   Úmaxrp   ÚfloatÚ	TypeErrorÚ
ValueErrorÚ_DISK_TTL_SECONDSr0   )rs   ÚdatarP   rV   rZ   ÚlvÚparsedÚages           r   Ú
_load_diskr„       s  € ä‹<€DØ€|ØðÜ�z‰z˜$Ÿ.™.°'˜.Ó:Ó;ˆØ—(‘(˜9Ó%ˆÜ˜'¤4Ô(±ØØJQÏ-É-Ë/×vÐv¹;¸3ÀÔ]gÐhnÔptÕ]u”#�c“(¨vÖ6¨œS �WÒ6Ñ6ÐvˆÒvð	+Ü�cœ4Ÿ9™9›;¬¨t¯x©x¸«~Ò/BÀÓ)CÑCÓDˆCð ’˜$ Ð$Ð$ùò 7ùÔvøô œ:Ð&ò 	+ÜÔ)Ó*ŠCð	+ûô ò Ùðúsf   �AD$ ÁD$ Á,C9ÂC9ÂC4Â%C9Â*D$ Â/=D  Ã,D$ Ã4C9Ã9D$ Ä D!ÄD$ Ä D!Ä!D$ Ä$	D0Ä/D0c                 óŽ   — t        | «      }|�+t        «       }t        5  ||_        ddd«       t	        |«       |S # 1 sw Y   ŒxY w)z8Seed memory + disk caches from a ``/v1/models`` payload.N)r]   r(   r&   r   rv   )rI   r‚   Ústates      r   Ú_seed_effortsr‡   ´   sF   € ä˜EÓ"€FØÐÜ“ˆÜñ 	*Ø#)ˆEÔ ÷	*ä�6ÔØ€M÷	*ð 	*ús	   ž;»Ar-   ç       @©Úapi_keyÚbase_urlÚtimeoutrŠ   r‹   rŒ   c                 ó”  — ddl }ddlm} |j                  j	                  |xs
 t        «       j                  d«      dz   «      }| xs
 t        «       }|r|j                  dd|› �«       |j                  dd	«       |j                  d
t        «       «       	  |||¬«      5 }t        j                  |j                  «       j                  «       «      }ddd«       t#        t$        «      r|n|j'                  dg «      }
t#        |
t$        «      r|
S dS # 1 sw Y   ŒAxY w# t        $ r }	t        j!                  d|	«       Y d}	~	yd}	~	ww xY w)zAFetch the raw ``/v1/models`` ``data`` array. None on any failure.r   N)Úopen_credentialed_urlr.   z/modelsÚAuthorizationzBearer ÚAcceptzapplication/jsonú
User-Agent)rŒ   z router: catalog fetch failed: %sr€   )Úurllib.requestÚhermes_cli.urllib_securityrŽ   ÚrequestÚRequestr<   r7   rA   Ú
add_headerr
   rn   ry   ÚreadÚdecoder0   rR   rr   rE   rQ   r4   )rŠ   r‹   rŒ   ÚurllibrŽ   ÚreqrG   Úrespr€   ru   rI   s              r   Ú_fetch_catalog_itemsrœ   ¿   s  € ãå@à
�.‰.×
 Ñ
  (Ò"9¬i«k×!AÑ!AÀ#Ó!FÈÑ!RÓ
S€CØ
Ò
'Ô%Ó'€CÙ
Ø�‰�¨'°#°¨Ô8Ø‡N�N�8Ð/Ô0Ø‡N�N�<Ô!4Ó!6Ô7ðÙ" 3°Ô8ð 	4¸DÜ—:‘:˜dŸi™i›k×0Ñ0Ó2Ó3ˆD÷	4ô
 ˜t¤TÔ*‰D°·±¸ÀÓ0D€EÜ˜u¤dÔ+ˆ5Ð5°Ð5÷	4ð 	4ûäò Ü�‰Ð7¸Ô=Üûðús0   Â
D Â 2DÃD ÄDÄD Ä	EÄ'EÅEc                  óP  — t        «       } t        5  | j                  }ddd«       €| j                  r|S d| _        t	        «       \  }}|€yt        5  | j                  €|| _        | j                  }ddd«       |t
        k\  r
t        «        |S # 1 sw Y   ŒsxY w# 1 sw Y   Œ*xY w)zQMemory, else the disk mirror (checked once per home). Never HTTP (hot-path safe).NT)r(   r&   r   r   r„   r   Ú_warm_efforts_async)r†   Úcachedr‚   rƒ   s       r   Ú_efforts_cache_onlyr    Õ   s§   € ä‹H€EÜ	ñ &Ø×%Ñ%ˆ÷&àÐ˜U×0Ò0ØˆØ€EÔÜ“,�K€FˆCØ€~ØÜ	ñ &Ø×ÑÐ'Ø#)ˆEÔ Ø×%Ñ%ˆ÷&ð ÔÒÜÔØ€M÷&ð &ú÷&ð &ús   ‘BÁ BÂBÂB%c                  óÈ  — t         j                  j                  d«      ryt        «       } t        5  | j
                  r
	 ddd«       yd| _        ddd«       t        «       sydd„}	 t        j                  t        j                  «       j                  |fdd¬«      j                  «        y# 1 sw Y   Œ^xY w# t        $ r }t        j                  d|«       Y d}~yd}~ww xY w)	zíRefresh the efforts cache in the background, at most once per home.

    Skipped under pytest (a mid-suite fetch makes cache state timing-dependent)
    and without a key (it would 401; the first authenticated fetch_models() seeds).
    ÚPYTEST_CURRENT_TESTNTc                  ó4   — t        «       } | �t        | «       y y )N)rœ   r‡   )rI   s    r   Ú_refreshz%_warm_efforts_async.<locals>._refreshù   s   € Ü$Ó&ˆØÐÜ˜%Õ ð r   zrouter-caps-warm)ÚtargetÚargsÚnameÚdaemonz'router: caps warmer failed to start: %sr   )r2   r3   r4   r(   r&   r   rA   Ú	threadingÚThreadÚcontextvarsÚcopy_contextÚrunÚstartr0   rR   rr   )r†   r¤   ru   s      r   rž   rž   é   sÅ   € ô 
‡z�z‡~�~Ð+Ô,ØÜ‹H€EÜ	ñ #Ø×ÒØ÷#ð #ð #ˆÔ÷#ô ÔØó!ðEô 	×ÑÜ×+Ñ+Ó-×1Ñ1¸¸ÐJ\Ðeiô	
ç
‰%�'÷!#ð #ûô" ò EÜ�‰Ð>À×DÑDûðEús*   ±B,ÁB,Á'AB8 Â,B5Â8	C!ÃCÃC!c                   óp   — e Zd ZdZddddœdee   dee   dedeee      fd	„Zd
ee   dee	edf      fd„Z
y)ÚRouterProfileuE   Ramp Router â€” Responses-only gateway with catalog-declared efforts.Nrˆ   r‰   rŠ   r‹   rŒ   r   c                óœ   — t        |xs d|xs d|¬«      }|€yt        |«       t        t        j	                  d„ |D «       «      «      xs dS )z“Live, key-scoped catalog; the same payload seeds the caps cache.
        Deduped but not sorted: Router's listing order is deliberate presentation.r-   r‰   Nc              3   ó~   K  — | ]5  }t        |t        «      sŒ|j                  d «      sŒ&t        |d    «      –— Œ7 y­w)rK   N)rE   rF   r4   r5   )Ú.0Úis     r   ú	<genexpr>z-RouterProfile.fetch_models.<locals>.<genexpr>  s0   è ø€ Ò!e°1ÄÈAÌtÕATÐYZ×Y^ÑY^Ð_cÕYd¤# a¨¡g§,Ñ!eùs   ‚=˜=ª=)rœ   r‡   rQ   rF   Úfromkeys)r   rŠ   r‹   rŒ   rI   s        r   Úfetch_modelszRouterProfile.fetch_models
  sL   € ô
 %¨Wª]¸ÀXÂ^ÐQSÐ]dÔeˆØˆ=ØÜ�eÔÜ”D—M‘MÑ!e¸Ô!eÓeÓfÒnÐjnÐnr   Úmodel.c                 ó˜   — t        |xs d«      j                  «       }|syt        «       }|€t        «        y||v rt	        ||   «      S dS )zKCatalog-declared effort vocabulary (cache-only; cold cache -> None + warm).r-   N)r5   r6   r    rž   Útuple)r   r¸   rV   rT   s       r   Úsupported_reasoning_effortsz)RouterProfile.supported_reasoning_efforts  sR   € ä�%’+˜2Ó×$Ñ$Ó&ˆÙØÜ+Ó-ˆØÐ ÜÔ!ØØ,/°=Ñ,@Œu�] 3Ñ'Ó(ÐJÀdÐJr   )r   r   r   r   r   r5   r|   rQ   r·   rº   r»   r   r   r   r°   r°     st   „ ÙOð +/È$Ðadò	oØ" 3™-ð	oØ:BÀ3¹-ð	oØY^ð	oà	�$�s‘)Ñ	ó	oð	K°¸#±ð 	KÀ8ÈEÐRUÐWZÐRZÉOÑC\ô 	Kr   r°   rL   )zramp-routerÚrampz
router.comÚcodex_responseszRamp Routeruc   Ramp Router (router.com) â€” routes each request to the cheapest model that clears your quality barzhttps://app.router.com/keys)r>   r?   r,   r‘   zHermes-Agent/Tzgpt-5.4-minir   )r§   ÚaliasesÚapi_modeÚdisplay_nameÚdescriptionÚ
signup_urlÚenv_varsr‹   Ú	auth_typeÚdefault_headersÚsupports_visionÚdefault_aux_modelÚfallback_modelsr   )6r   r«   rn   Úloggingr2   r$   r©   rp   Úpathlibr   Útypingr   r   Úagent.reasoning_effortr   Ú
hermes_clir   Ú_HERMES_VERSIONÚ	providersr   Úproviders.baser	   r
   Ú	getLoggerr   rR   r8   r   rF   r5   rQ   Ú__annotations__ÚLockr&   r   r   r   r   r(   r<   rA   rH   r]   rb   rv   rº   r|   r„   r‡   rœ   r    rž   r°   rL   r   r   r   ú<module>rÔ      s7  ðòó Û Û Û 	Û 
Û Û Ý ß  å 0Ý 5Ý 'ß ?à	ˆ×	Ñ	˜8Ó	$€à5Ð ð 26€�˜˜c 4¨¡9˜nÑ-Ñ.Ó 5Ø�	—‘Ó €Ø€Ø€÷#ñ #ð *,€��S˜+Ð%Ñ&Ó +ðK�ó Kð#�3ó #ð ˜#ó ð$ˆcð ˜#ð  #ó ð!˜#ð ! (¨4°°T¸#±Y°Ñ+?Ñ"@ó !ð@�H˜T‘Nó ð
G˜d 3¨¨S©	 >Ñ2ð 
G°tó 
Gð�E˜( 4¨¨T°#©Y¨Ñ#7Ñ8¸%Ð?Ñ@ó ð(˜ð  ¨$¨s°D¸±I¨~Ñ*>Ñ!?ó ð ,.¸rÐTWò 6 Sð 6¸ð 6ÈEð 6Ð\dÐeiÑ\jó 6ð,˜X d¨3°°S±	¨>Ñ&:Ñ;ó ó(Eô<K�Oô Kñ4 
Ø	Ð@ÐK\ØØuØ,ØNÑYbÓYdØà! ]°?Ð2CÐ#DÐEØ¨NØô
€ñ �&Õ r   