§
    øžyjÕ'  ã                   ó  — U d Z ddlZddlmZ ddlmZ ddlmZ ddlm	Z	 ddl
mZ  ej        e¦  «        Zdaee         dz  ed<   d	Zd
edz  defd„Z G d„ de¦  «        Z eddddddddd¬¦	  «	        Z e	e¦  «         dS )zOpenRouter provider profile.é    N)ÚAny)Úget_conversation_context)Ú_cache_scope_from_session_id)Úregister_provider)ÚProviderProfileÚ_CACHE)zclaude-3zclaude-opus-4-0zclaude-opus-4.0zclaude-opus-4-1zclaude-opus-4.1zclaude-sonnet-4-0zclaude-sonnet-4.0zclaude-opus-4-2025zclaude-sonnet-4-2025zclaude-opus-4-5zclaude-opus-4.5zclaude-sonnet-4-5zclaude-sonnet-4.5zclaude-haiku-4-5zclaude-haiku-4.5ÚmodelÚreturnc                 ó¨   ‡— | pd                      ¦   «         Š‰                     d¦  «        sd‰vrdS t          ˆfd„t          D ¦   «         ¦  «         S )u¢  Return True for Anthropic models that reject any disable-thinking form.

    Claude 4.6+ (adaptive thinking) and newer named models have no "off"
    switch â€” sending ``reasoning: {enabled: false}`` makes OpenRouter emit
    ``thinking: {type: "disabled"}``, which these models 400 on. Unknown /
    new Anthropic model names default to mandatory so the next un-numbered
    release doesn't reintroduce the 400.
    Ú )z
anthropic/Úclauder   Fc              3   ó    •K  — | ]}|‰v V — Œ	d S )N© )Ú.0ÚsubÚms     €úQ/home/ragecks/.hermes/hermes-agent/plugins/model-providers/openrouter/__init__.pyú	<genexpr>z4_anthropic_reasoning_is_mandatory.<locals>.<genexpr>.   s'   øè è € ÐPÐP �3˜!�8ÐPÐPÐPÐPÐPÐPó    )ÚlowerÚ
startswithÚanyÚ(_ANTHROPIC_REASONING_OPTIONAL_SUBSTRINGS)r	   r   s    @r   Ú!_anthropic_reasoning_is_mandatoryr   "   se   ø€ ð 
ˆ�"×ÒÑÔ€AØ�<Š<Ð0Ñ1Ô1ð °hÀaÐ6GÐ6GØˆuÝÐPÐPÐPÐPÕ'OÐPÑPÔPÑPÔPÐPÐPr   c                   óú   ‡ — e Zd ZdZddddœdedz  dedz  dedee         dz  fˆ fd	„Zdd
œdedz  dede	eef         fd„Z
dddddœde	dz  dededz  dedz  dedee	eef         e	eef         f         fd„Zˆ xZS )ÚOpenRouterProfileuM   OpenRouter aggregator â€” provider preferences, reasoning config passthrough.Ng       @©Úapi_keyÚbase_urlÚtimeoutr   r   r    r
   c                óÜ   •— t           �t           S 	 t          ¦   «                              d||¬¦  «        }|�|a |S # t          $ r&}t                               d|¦  «         Y d}~dS d}~ww xY w)u|  Fetch from public OpenRouter catalog â€” no auth required.

        Note: Tool-call capability filtering is applied by hermes_cli/models.py
        via fetch_openrouter_models() â†’ _openrouter_model_supports_tools(), not
        here. The picker early-returns via the dedicated openrouter path before
        reaching this method, so filtering here would be unreachable.
        Nr   zfetch_models(openrouter): %s)r   ÚsuperÚfetch_modelsÚ	ExceptionÚloggerÚdebug)Úselfr   r   r    ÚresultÚexcÚ	__class__s         €r   r#   zOpenRouterProfile.fetch_models4   s…   ø€ õ ÐÝˆMð	Ý‘W”W×)Ò)°$ÀÐSZÐ)Ñ[Ô[ˆFØÐ!Ø�ØˆMøÝð 	ð 	ð 	Ý�LŠLÐ7¸Ñ=Ô=Ð=Ø�4�4�4�4�4øøøøð	øøøs   ‘); »
A+ÁA&Á&A+)Ú
session_idr+   Úcontextc                óˆ  — i }t          t          ¦   «         p|¦  «        }|r||d<   |                     d¦  «        }|r||d<   |                     d¦  «        pd}|dk    rb|                     d¦  «        }|�K|dk    rE	 t          |¦  «        }n# t          t
          f$ r d }Y nw xY w|�d|cxk    rd	k    rn n	d
|dœg|d<   |S )Nr+   Úprovider_preferencesÚproviderr	   r   zopenrouter/pareto-codeÚopenrouter_min_coding_scoreg        g      ð?zpareto-router)ÚidÚmin_coding_scoreÚplugins)r   r   ÚgetÚfloatÚ	TypeErrorÚ
ValueError)	r'   r+   r,   ÚbodyÚ
sticky_keyÚprefsr	   ÚscoreÚscore_fs	            r   Úbuild_extra_bodyz"OpenRouterProfile.build_extra_bodyN   s  € ð  "ˆõ$ 2Õ2JÑ2LÔ2LÐ2ZÐPZÑ[Ô[ˆ
Øð 	,Ø!+ˆD�ÑØ—’Ð2Ñ3Ô3ˆØð 	%Ø$ˆD�Ñð —’˜WÑ%Ô%Ð+¨ˆØÐ,Ò,Ð,Ø—K’KÐ =Ñ>Ô>ˆEØÐ  U¨b¢[ [ð#Ý# E™lœl�G�GøÝ!¥:Ð.ð #ð #ð #Ø"�G�G�Gð#øøøàÐ&¨3°'Ð+@Ð+@Ò+@Ð+@¸SÒ+@Ð+@Ð+@Ð+@Ð+@à.ÀGÐLÐLð'�D˜‘Oð ˆs   Á>B ÂB$Â#B$F)Úreasoning_configÚsupports_reasoningr	   r+   r>   r?   r	   c                ót  — i }i }i }|rkt          |¦  «        r?|pi }	|	                     d¦  «        }
|	                     dd¦  «        dur|
r|
dk    r|
|d<   n|�t          |¦  «        |d<   ndd	d
œ|d<   t          t	          ¦   «         p|¦  «        }|r|r|                     d¦  «        r||d<   |r||d<   ||fS )a  OpenRouter passes the full reasoning_config dict as extra_body.reasoning.

        For xAI Grok models routed through OpenRouter, attach the
        ``x-grok-conv-id`` header so that xAI's prompt cache stays pinned to
        the same backend server across turns.
        ÚeffortÚenabledTFÚnoneÚ	verbosityNÚ	reasoningÚmedium)rB   rA   )z
x-ai/grok-z	xai/grok-zx-grok-conv-idÚextra_headers)r   r4   Údictr   r   r   )r'   r>   r?   r	   r+   r,   Ú
extra_bodyÚ	top_levelrG   ÚcfgrA   Úgrok_conv_ids               r   Úbuild_api_kwargs_extrasz)OpenRouterProfile.build_api_kwargs_extras|   s  € ð &(ˆ
Ø$&ˆ	Ø(*ˆØð &	Põ6 1°Ñ7Ô7ð PØ&Ð,¨"�ØŸš Ñ*Ô*�ð —7’7˜9 dÑ+Ô+°5Ð8Ð8¸VÐ8ÈÐRXÒHXÐHXØ-3�I˜kÑ*øØ!Ð-Ý*.Ð/?Ñ*@Ô*@�
˜;Ñ'Ð'à6:ÀhÐ*OÐ*O�
˜;Ñ'õ 4Õ4LÑ4NÔ4NÐ4\ÐR\Ñ]Ô]ˆØð 	;˜Eð 	; e×&6Ò&6Ð7RÑ&SÔ&Sð 	;Ø.:ˆMÐ*Ñ+Øð 	7Ø)6ˆI�oÑ&à˜9Ð$Ð$r   )Ú__name__Ú
__module__Ú__qualname__Ú__doc__Ústrr5   Úlistr#   r   rH   r=   ÚboolÚtuplerM   Ú__classcell__)r*   s   @r   r   r   1   sw  ø€ € € € € ØWÐWð
 #Ø#Øðð ð ð �t‘ðð ˜‘*ð	ð
 ðð 
ˆcŒ�TÑ	ðð ð ð ð ð ð6 +/ð,ð ,ð ,Ø  4™Zð,Ø;>ð,à	ˆc�3ˆhŒð,ð ,ð ,ð ,ðb )-Ø#(Ø Ø!%ðD%ð D%ð D%ð  ™+ðD%ð !ð	D%ð
 �T‰zðD%ð ˜$‘JðD%ð ðD%ð 
ˆt�C˜�HŒ~˜t C¨ Hœ~Ð-Ô	.ðD%ð D%ð D%ð D%ð D%ð D%ð D%ð D%r   r   Ú
openrouter)Úor)ÚOPENROUTER_API_KEYÚ
OpenRouteru*   OpenRouter â€” unified API for 200+ modelszhttps://openrouter.ai/keyszhttps://openrouter.ai/api/v1z#https://openrouter.ai/api/v1/models)zanthropic/claude-sonnet-4.6zopenai/gpt-5.4zdeepseek/deepseek-chatzgoogle/gemini-3.6-flashzqwen/qwen3-plus)	ÚnameÚaliasesÚenv_varsÚdisplay_nameÚdescriptionÚ
signup_urlr   Ú
models_urlÚfallback_models)rQ   ÚloggingÚtypingr   Úagent.portal_tagsr   Úagent.transports.codexr   Ú	providersr   Úproviders.baser   Ú	getLoggerrN   r%   r   rS   rR   Ú__annotations__r   rT   r   r   rW   r   r   r   ú<module>rk      sR  ðØ "Ð "Ð "à €€€Ø Ð Ð Ð Ð Ð à 6Ð 6Ð 6Ð 6Ð 6Ð 6Ø ?Ð ?Ð ?Ð ?Ð ?Ð ?Ø 'Ð 'Ð 'Ð 'Ð 'Ð 'Ø *Ð *Ð *Ð *Ð *Ð *à	ˆÔ	˜8Ñ	$Ô	$€à€ˆˆSŒ	�DÑÐ Ð Ñ ð,Ð (ðQ¨S°4©Zð Q¸Dð Qð Qð Qð QðO%ð O%ð O%ð O%ð O%˜ñ O%ô O%ð O%ðd ÐØ	ØØ$ØØ<Ø+Ø+Ø4ððñ ô €
ð$ Ð �*Ñ Ô Ð Ð Ð r   