
    
Bjs                        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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                  d   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<    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"	 	 	 	 	 d+d#Zdd$	 	 	 	 	 d,d%Zdd&d'	 	 	 	 	 d-d(Zy).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_checkfallback_modelshostname)default_factoryzdict[str, str]default_headersNr   fixed_temperaturez
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     3/home/ubuntu/.hermes/hermes-agent/providers/base.pyget_hostnamezProviderProfile.get_hostnameD   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_messagesQ   s	     r(   )
session_idc                   i S )zrProvider-specific extra_body fields.

        Merged into the API kwargs extra_body. Default: empty dict.
        r   )r%   r,   contexts      r&   build_extra_bodyz ProviderProfile.build_extra_bodyY   s	     	r(   )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%   r0   r.   s      r&   build_api_kwargs_extrasz'ProviderProfile.build_api_kwargs_extrasb   s    $ 2vr(   g       @)r   timeoutc               j   | j                   xs dj                         }|s+| j                  sy| j                  j                  d      dz   }ddl}ddl}|j                  j                  |      }|r|j                  dd|        |j                  dd	       | j                  j                         D ]  \  }}|j                  ||        	 |j                  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| j,                  |       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. 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   AuthorizationzBearer Acceptzapplication/json)r3   dataidzfetch_models(%s): %s)r   stripr   rstripjsonurllib.requestrequestRequest
add_headerr   itemsurlopenloadsreaddecode
isinstancelistgetdict	Exceptionloggerdebugr
   )r%   r   r3   urlr<   urllibreqkvrespr8   rA   mexcs                 r&   fetch_modelszProviderProfile.fetch_modelsv   sn   2 $"++-==--&&s+i7Cnn$$S)NN?ggY,?@x!34((..0 	!DAqNN1a 	!	''W'= 8zz$))+"4"4"678&tT2D8LE%*PjD.AdaiAdGPP8 8 Q 	LL/C@	sH   E> *.E-0E> E9E9#E9*E> -E62E> >	F2!F--F2)returnr	   )r*   list[dict[str, Any]]rV   rW   )r,   
str | Noner.   r   rV   zdict[str, Any])r0   zdict | Noner.   r   rV   z%tuple[dict[str, Any], dict[str, Any]])r   rX   r3   floatrV   zlist[str] | None)__name__
__module____qualname____doc____annotations__r   r   r   r   r   r   r   r   r   r   r   r   r   rI   r   r   r    r!   r'   r+   r/   r2   rU   r   r(   r&   r   r      sD   K I&Hc&GU L#KJ HeHcJIs"&4&
  OU Hc ',D&AO^A "s!%)
)
 s  +/';>	 )- & 	
 
/. #	0 0 	0
 
0r(   r   )r]   
__future__r   loggingdataclassesr   r   typingr   	getLoggerrZ   rK   objectOMIT_TEMPERATUREr   r   r(   r&   <module>rf      sP   	 #  ( 			8	$ 8  M M Mr(   