
    `gj                          U d Z ddl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       y)zOpenRouter provider profile.    N)Any)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                     | xs dj                         j                  d      sdvry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  
 y w)N ).0subms     ^/root/.hermes/venv/lib/python3.12/site-packages/plugins/model-providers/openrouter/__init__.py	<genexpr>z4_anthropic_reasoning_is_mandatory.<locals>.<genexpr>,   s     P3!8Ps   )lower
startswithany(_ANTHROPIC_REASONING_OPTIONAL_SUBSTRINGS)r   r   s    @r   !_anthropic_reasoning_is_mandatoryr       sC     
"A<<01ha6GP'OPPPP    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        j                  d|       Y d}~y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_models2   s^     M	W)$SZ)[F!M 	LL7=	s   ' 	AAA)
session_idr)   contextc                &   i }|r||d<   |j                  d      }|r||d<   |j                  d      xs d}|dk(  r>|j                  d      }|+|dk7  r&	 t        |      }|d|cxk  rd	k  rn |S d
|dg|d<   |S # t        t        f$ r d }Y /w xY w)Nr)   provider_preferencesproviderr   r
   zopenrouter/pareto-codeopenrouter_min_coding_scoreg        g      ?zpareto-router)idmin_coding_scoreplugins)getfloat	TypeError
ValueError)r%   r)   r*   bodyprefsr   scorescore_fs           r   build_extra_bodyz"OpenRouterProfile.build_extra_bodyL   s      "!+D23$D W%+,,KK =>E Ub[##ElG &3'+@S+@   /GL'DO  ":. #"G#s   A< <BBF)reasoning_configsupports_reasoningr   r)   r;   r<   r   c                   i }i }i }|r\t        |      r8|xs i }	|	j                  d      }
|	j                  dd      dur&|
r$|
dk7  r|
|d<   n|t        |      |d<   nddd	|d<   |r|r|j                  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	verbosity	reasoningmedium)r?   r>   )z
x-ai/grok-z	xai/grok-zx-grok-conv-idextra_headers)r   r2   dictr   )r%   r;   r<   r   r)   r*   
extra_body	top_levelrD   cfgr>   s              r   build_api_kwargs_extrasz)OpenRouterProfile.build_api_kwargs_extrash   s     &(
$&	(*6 17&,"* 779d+58VRXHX-3Ik*!-*./?*@
;'6:h*O
;'%E$4$45P$Q.8M*+)6Io&9$$r   )__name__
__module____qualname____doc__strr3   listr!   r   rE   r:   booltuplerI   __classcell__)r(   s   @r   r   r   /   s    W
 ## t *	
  
cT	6 +/ 4Z;>	c3h> )-#( !%?% +?% !	?%
 Tz?% $J?% ?% 
tCH~tCH~-	.?%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-flash-previewzqwen/qwen3-plus)	namealiasesenv_varsdisplay_namedescription
signup_urlr   
models_urlfallback_models)rM   loggingtypingr   	providersr   providers.baser   	getLoggerrJ   r#   r   rO   rN   __annotations__r   rP   r   r   rS   r   r   r   <module>re      s    "   ' *			8	$S	D , (QS4Z QD Qx% x%v 	$<++4
$ * r   