
    `gj&                        d Z ddlmZ ddlZddlmZmZ ddlmZ  ej                  e
      Z e       Zd	dZe G d d             Zy)
u  Provider profile base class.

A ProviderProfile declares everything about an inference provider in one place:
auth, endpoints, client quirks, request-time quirks. The transport reads this
instead of receiving 20+ boolean flags.

Provider profiles are DECLARATIVE — they describe the provider's behavior.
They do NOT own client construction, credential rotation, or streaming.
Those stay on AIAgent.
    )annotationsN)	dataclassfield)Anyc                 8    	 ddl m}  d|  S # t        $ r Y yw xY w)u  Return a ``hermes-cli/<version>`` UA string, with a stable fallback.

    Used by ``ProviderProfile.fetch_models`` so the catalog probe is not
    served the default ``Python-urllib/<ver>`` UA — some providers
    (OpenCode Zen, etc.) sit behind a WAF that returns 403 for that.
    r   )__version__zhermes-cli/z
hermes-cli)
hermes_clir   	Exception)_vers    A/root/.hermes/venv/lib/python3.12/site-packages/providers/base.py_profile_user_agentr      s)    2TF## s   
 	c                     e Zd ZU dZded<   dZded<   dZded<   d	Zded
<   d	Zded<   d	Z	ded<   dZ
ded<   d	Zded<   d	Zded<   dZded<   dZded<   dZded<   dZded<   dZded<   d	Zded<    ee      Zded<   dZded<   dZd ed!<   d	Zded"<   d.d#Zd/d$Zdd%	 	 	 	 	 d0d&Zdd'	 	 	 	 	 d1d(Zd2d)Zd3d*Zddd+d,	 	 	 	 	 	 	 d4d-Zy)5ProviderProfileuA   Base provider profile — subclass or instantiate with overrides.strnamechat_completionsapi_mode tuplealiases display_namedescription
signup_urlenv_varsbase_url
models_urlapi_key	auth_typeTboolsupports_health_checkFsupports_visionsupports_vision_tool_messagesfallback_modelshostname)default_factoryzdict[str, str]default_headersNr   fixed_temperature
int | Nonedefault_max_tokensdefault_aux_modelc                    | j                   r| j                   S | j                  r&ddlm}  || j                        j                   xs dS y)u   Return the provider's base hostname for URL-based detection.

        Uses self.hostname if set explicitly, otherwise derives it from base_url.
        e.g. 'https://api.gmi-serving.com/v1' → 'api.gmi-serving.com'
        r   )urlparser   )r%   r   urllib.parser-   )selfr-   s     r   get_hostnamezProviderProfile.get_hostnameb   s<     ==== ==-DMM*339r9    c                    |S )zProvider-specific message preprocessing.

        Called AFTER codex field sanitization, BEFORE developer role swap.
        Default: pass-through.
        r   )r/   messagess     r   prepare_messagesz ProviderProfile.prepare_messageso   s	     r1   )
session_idc                   i S )zrProvider-specific extra_body fields.

        Merged into the API kwargs extra_body. Default: empty dict.
        r   )r/   r5   contexts      r   build_extra_bodyz ProviderProfile.build_extra_bodyw   s	     	r1   )reasoning_configc               
    i i fS )a  Provider-specific kwargs split between extra_body and top-level api_kwargs.

        Returns (extra_body_additions, top_level_kwargs).
        The transport merges extra_body_additions into extra_body, and
        top_level_kwargs directly into api_kwargs.

        This split exists because some providers put reasoning config in
        extra_body (OpenRouter: extra_body.reasoning) while others put it
        as top-level api_kwargs (Kimi: api_kwargs.reasoning_effort).

        Default: ({}, {}).
        r   )r/   r9   r7   s      r   build_api_kwargs_extrasz'ProviderProfile.build_api_kwargs_extras   s    $ 2vr1   c                     y)u  Return a default vision model id for this provider, or None.

        Overrideable hook for providers that discover their vision default at
        runtime (e.g. from a live catalog) rather than pinning one in code.
        Keeps provider-specific vision discovery inside the provider's plugin
        instead of a name-check branch in shared vision resolution.

        Default: None (no provider-specific vision model — the caller falls
        back to the user's chat model or the aggregator chain).
        Nr   )r/   s    r   default_vision_modelz$ProviderProfile.default_vision_model   s     r1   c                    | j                   S )u  Return the default max_tokens cap for *model*.

        Overrideable hook for providers that need per-model output caps —
        e.g. a relay that fronts several upstream backends, each with a
        different completion-token limit. The transport calls this when
        the user hasn't set an explicit max_tokens.

        Default: return self.default_max_tokens (the static profile field),
        ignoring the model name. Override in a subclass to vary the cap
        per-model.
        )r*   )r/   models     r   get_max_tokenszProviderProfile.get_max_tokens   s     &&&r1   g       @)r   r   timeoutc               |   |xs | j                   }| j                  xs dj                         }|s|sy|j                  d      dz   }ddl}ddl}ddlm} |j                  j                  |      }	|r|	j                  dd|        |	j                  d	d
       |	j                  dt                      | j                  j                         D ]  \  }
}|	j                  |
|        	  ||	|      5 }|j                  |j                         j!                               }ddd       t#        t$              r|n|j'                  dg       }|D cg c]  }t#        |t(              sd|v s|d    c}S # 1 sw Y   VxY wc c}w # t*        $ r+}t,        j/                  d| j0                  |       Y d}~yd}~ww xY w)u  Fetch the live model list from the provider's models endpoint.

        Returns a list of model ID strings, or None if the fetch failed or
        the provider does not support live model listing.

        Resolution order for the endpoint URL:
          1. self.models_url  (explicit override — use when the models
             endpoint differs from the inference base URL, e.g. OpenRouter
             exposes a public catalog at /api/v1/models while inference is
             at /api/v1)
          2. base_url (caller override — user-configured model.base_url)
          3. self.base_url + "/models"  (standard OpenAI-compat fallback)

        The default implementation sends Bearer auth when api_key is given
        and forwards self.default_headers. Override to customise auth, path,
        response shape, or to return None for providers with no REST catalog.

        Callers must always fall back to the static _PROVIDER_MODELS list
        when this returns None.
        r   N/z/modelsr   )open_credentialed_urlAuthorizationzBearer Acceptzapplication/jsonz
User-Agent)rA   dataidzfetch_models(%s): %s)r   r   striprstripjsonurllib.requesthermes_cli.urllib_securityrD   requestRequest
add_headerr   r'   itemsloadsreaddecode
isinstancelistgetdictr
   loggerdebugr   )r/   r   r   rA   effective_baseurlrK   urllibrD   reqkvresprG   rQ   mexcs                    r   fetch_modelszProviderProfile.fetch_models   s~   6 "2T]]$"++-! '',y8CDnn$$S)NN?ggY,?@x!34 	|%8%:;((..0 	!DAqNN1a 	!	&sG< 8zz$))+"4"4"678&tT2D8LE%*PjD.AdaiAdGPP8 8 Q 	LL/C@	sH   )
F 3.E6!0F F'F,F3F 6E?;F 	F;!F66F;returnr   )r3   list[dict[str, Any]]rf   rg   )r5   
str | Noner7   r   rf   zdict[str, Any])r9   zdict | Noner7   r   rf   z%tuple[dict[str, Any], dict[str, Any]])rf   rh   )r?   rh   rf   r)   )r   rh   r   rh   rA   floatrf   zlist[str] | None) __name__
__module____qualname____doc____annotations__r   r   r   r   r   r   r   r   r   r!   r"   r#   r$   r%   r   rX   r'   r(   r*   r+   r0   r4   r8   r;   r=   r@   rd   r   r1   r   r   r   &   st   K I&Hc&GU L#KJ HeHcJIs"&4& "OT! +/!4.
  OU Hc ',D&AO^A "s!%)
)
 s  +/';>	 )- & 	
 
/('" ##9 9 	9
 9 
9r1   r   re   )rm   
__future__r   loggingdataclassesr   r   typingr   	getLoggerrj   rY   objectOMIT_TEMPERATUREr   r   r   r1   r   <module>rv      sU   	 #  ( 			8	$ 8  A A Ar1   