
    `gjn                       U d Z ddlmZ ddlZddlmZ ddlmZmZm	Z	m
Z
mZ ddlmZmZ  ej                  e      Z ed       G d	 d
             Zi d eddd      d eddd      d eddd      d eddd      d eddd      d edddd !      d" eddd#d$!      d% edd&d'd(d)*      d+ edd,d-d.!      d/ edd01      d2 ed3d41      d5 edd6d78      d9 edd:;      d< edd=d>d?@      dA ed3dB;      dC ed3ddD      dE ed3dF;      i dG eddH;      dI eddJ;      dK eddL;      dM edddN      dO edddP      dQ edddR      dS edddT      dU edddV      dW eddd       dX eddYdZ      d[ edd\;      d] edd^;      d_ edd`da      db eddcddde@      df eddgdhi      dj eddkdldm@      dn eddodp       eddq;       edrdst      duZdvedw<   e G dx dy             Zi dzdd{d5d|d5d}d5d~d5ddWddWddWddddddddddXddXddXddXdd9i dd9dd9dd9dd<dd<ddEddEdd2dd2dd/dd/dd+ddMddMddOddOddQi ddQddQddGddIddIddIddIddKddKddKddSddSddSddUddUdd[dd[i dd]dd]dd]dd]dddddddddd_dd_ddbddbddfddfddjd%d%dd%d%ddddddZded<   dddddddddddddddМZded<   dd3ddrdӜZded<   ddՄZddքZddׄZdd؄Z edOdMh      Zded<   ddۄZddd܄Z ddd݄Z!ddބZ"dd߄Z#	 	 	 	 	 	 ddZ$	 	 d	 	 	 	 	 	 	 ddZ%y)u  
Single source of truth for provider identity in Hermes Agent.

Two data sources, merged at runtime:

1. **models.dev catalog** — 109+ providers with base URLs, env vars, display
   names, and full model metadata (context, cost, capabilities).  This is
   the primary database.

2. **Hermes overlays** — transport type, auth patterns, aggregator flags,
   and additional env vars that models.dev doesn't track.  Small dict,
   maintained here.

3. **User config** (``providers:`` section in config.yaml) — user-defined
   endpoints and overrides.  Merged on top of everything else.

Other modules import from this file.  No parallel registries.
    )annotationsN)	dataclass)AnyDictListOptionalTuple)base_url_host_matchesbase_url_hostnameT)frozenc                  f    e Zd ZU dZ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<   y)HermesOverlayz?Hermes-specific provider metadata layered on top of models.dev.openai_chatstr	transportFboolis_aggregatorapi_key	auth_type Tuple[str, ...]extra_env_vars base_url_overridebase_url_env_varN)__name__
__module____qualname____doc__r   __annotations__r   r   r   r   r   r       G/root/.hermes/venv/lib/python3.12/site-packages/hermes_cli/providers.pyr   r   "   sC    I"Is"M4Is&(NO(scr!   r   moar   virtualzmoa://local)r   r   r   
openrouterOPENROUTER_BASE_URL)r   r   r   nousoauth_device_codez)https://inference-api.nousresearch.com/v1openai-codexcodex_responsesoauth_externalz%https://chatgpt.com/backend-api/codexz
openai-apizhttps://api.openai.com/v1OPENAI_BASE_URL)r   r   r   	xai-oauthzhttps://api.x.ai/v1XAI_BASE_URL)r   r   r   r   z
qwen-oauthzhttps://portal.qwen.ai/v1HERMES_QWEN_BASE_URLlmstudior   )
LM_API_KEYzhttp://127.0.0.1:1234/v1LM_BASE_URL)r   r   r   r   r   copilot-acpexternal_processzacp://copilotCOPILOT_ACP_BASE_URLzgithub-copilot)COPILOT_GITHUB_TOKENGH_TOKEN)r   r   	anthropicanthropic_messages)ANTHROPIC_TOKENCLAUDE_CODE_OAUTH_TOKENzai)GLM_API_KEYZAI_API_KEYZ_AI_API_KEYGLM_BASE_URL)r   r   r   zkimi-for-codingKIMI_BASE_URL)r   r   stepfun)STEPFUN_API_KEYz#https://api.stepfun.ai/step_plan/v1STEPFUN_BASE_URL)r   r   r   r   minimaxMINIMAX_BASE_URLzminimax-oauthz https://api.minimax.io/anthropicz
minimax-cnMINIMAX_CN_BASE_URLdeepseekDEEPSEEK_BASE_URLalibabaDASHSCOPE_BASE_URLzalibaba-coding-planALIBABA_CODING_PLAN_BASE_URLopencodeOPENCODE_ZEN_BASE_URLzopencode-goOPENCODE_GO_BASE_URLkiloKILOCODE_BASE_URLhuggingfaceHF_BASE_URLnovitaNOVITA_BASE_URLxainvidiaz#https://integrate.api.nvidia.com/v1NVIDIA_BASE_URLxiaomiXIAOMI_BASE_URLtencent-tokenhubTOKENHUB_BASE_URLarceezhttps://api.arcee.ai/api/v1ARCEE_BASE_URLgmi)GMI_API_KEYzhttps://api.gmi-serving.com/v1GMI_BASE_URL	fireworks)FIREWORKS_API_KEYz%https://api.fireworks.ai/inference/v1)r   r   r   upstage)UPSTAGE_API_KEYzhttps://api.upstage.ai/v1UPSTAGE_BASE_URLollama-cloudzhttps://ollama.com/v1OLLAMA_BASE_URLAZURE_FOUNDRY_BASE_URLbedrock_converseaws_sdk)r   r   )zazure-foundrybedrockzDict[str, HermesOverlay]HERMES_OVERLAYSc                      e Zd ZU dZded<   ded<   ded<   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<   y)ProviderDefu9   Complete provider definition — merged from all sources.r   idnamer   r   api_key_env_varsr   base_urlr   Fr   r   r   r   docsourceN)r   r   r   r   r    rs   r   r   r   rt   ru   r   r!   r"   ro   ro      sV    CG
IN%%HccM4IsCMFCr!   ro   openaiglmzz-aizz.aizhipuzx-aizx.aigrokz
grok-oauthz
x-ai-oauthzxai-grok-oauthnimz
nvidia-nimzbuild-nvidianemotronkimizkimi-codingzkimi-coding-cnmoonshotstepzstepfun-coding-planzminimax-china
minimax_cnclaudezclaude-codecopilotgithubzgithub-copilot-acpzopencode-zenzengozopencode-go-subkilocodez	kilo-codezkilo-gatewayz	deep-seek	dashscopealiyunqwenzalibaba-cloudalibaba_codingzalibaba-codingalibaba_coding_planhfzhugging-facezhuggingface-hubz	novita-ainovitaaimimozxiaomi-mimotencenttokenhubztencent-cloudtencentmaasawsrl   zaws-bedrockzamazon-bedrockamazonzarcee-aiarceeaiz	gmi-cloudgmicloudzfireworks-aifwsolarz	lm-studiocustomlocal)	lm_studioollamavllmllamacppz	llama.cppz	llama-cppzDict[str, str]ALIASESzMixture of AgentszNous PortalzOpenAI CodexzGitHub Copilot ACPzStepFun Step PlanzXiaomi MiMoz	GMI CloudzUpstage SolarzTencent TokenHubz	LM StudiozLocal endpointzAWS BedrockzOllama Cloudz%xAI Grok OAuth (SuperGrok / Premium+))r#   r'   r)   r3   rB   rY   r_   rd   r[   r0   r   rl   rg   r-   _LABEL_OVERRIDESchat_completions)r   r9   r*   rj   TRANSPORT_TO_API_MODEc                j    | j                         j                         }t        j                  ||      S )zResolve aliases and normalise casing to a canonical provider id.

    Returns the canonical id string.  Does *not* validate that the id
    corresponds to a known provider.
    )striplowerr   get)rq   keys     r"   normalize_providerr     s)     **,


C;;sC  r!   c                
   t        |       }	 ddlm}  ||      }t        j                  |      }||r|j                  nd}|r|j                  nd}|r|j                  nd}|r|j                  nd}|r|j                  nd}	t        |j                        }
|r3|j                  r'|j                  D ]  }||
vs|
j                  |        t        ||j                   |t#        |
      |	xs |j$                  ||||j&                  d	
      S |dt        |t(        j                  ||      |j                  |j                  |j                  |j                  |j                  |j                  d
	      S y# t        $ r d}Y fw xY w)aA  Look up a built-in provider by id or alias.

    Resolution order:
      1. Hermes overlays (for providers not in models.dev: nous, openai-codex, etc.)
      2. models.dev catalog + Hermes overlay

    User-defined providers from config.yaml (``providers:`` / ``custom_providers:``)
    are resolved by :func:`resolve_provider_full`, which layers ``resolve_user_provider``
    and ``resolve_custom_provider`` on top of this function. Callers that need
    user-config support should use ``resolve_provider_full`` instead.

    Returns a fully-resolved ProviderDef or None.
    r   get_provider_infoNr   Fr   r   
models.dev)
rp   rq   r   rr   rs   r   r   r   rt   ru   hermes)	rp   rq   r   rr   rs   r   r   r   ru   )r   agent.models_devr   	Exceptionrm   r   r   r   r   r   r   listenvr   appendro   rq   tupleapirt   r   )rq   	canonical_mdev_provider	mdev_infooverlayr   is_aggauthbase_url_envr   env_varsevs               r"   get_providerr     s    #4(IH"9-	 !!),G)0G%%m	*1&&u$+w  3:w//9@G55b 	&w--,, (X%OOB'( "8_&7)--) 
 	
 !%%i;''$33..$55!//''

 
	
 _  	s   E3 3FFc                p    t        |       }|t        v r	t        |   S t        |      }|r|j                  S |S )z1Get a human-readable display name for a provider.)r   r   r   rq   )provider_idr   pdefs      r"   	get_labelr     sA    ";/I $$	** 	"Dyyr!   c                z    t        | xs d      }|j                  d      ryt        |      }|r|j                  S dS )z:Return True when the provider is a multi-model aggregator.r   custom:TF)r   
startswithr   r   )providerprovider_normr   s      r"   r   r     s>    &x~26M	*&D!%4050r!   zfrozenset[str]_FLAT_NAMESPACE_RESELLERSc                H    t        | xs d      }|t        v ryt        |      S )ux  Return True only for TRUE routing aggregators (e.g. OpenRouter, named
    ``custom:*`` proxies) — those that route bare/vendor-slugged model names
    to *other* providers' endpoints.

    Distinct from :func:`is_aggregator`, which also reports True for
    flat-namespace resellers (opencode-go/zen) whose catalog is entirely
    first-party. Use this gate when the question is "would selecting this
    model silently re-route the call away from the user's intended provider?"
    — i.e. the picker dedup. Resellers answer no: their listed models are
    their own, so their rows must not be deduped against user proxies.
    r   F)r   r   r   )r   r   s     r"   is_routing_aggregatorr     s)     'x~26M11''r!   c                    | sy| j                  d      j                         }t        |       }|dk(  rd|v ry|dk(  s|j                  d      ry|dk(  ry	|j	                  d
      rt        | d      ryy)u;  Return the wire protocol a specific endpoint *requires*, or None.

    Some hosts only accept one API mode and reject the others outright:
      - api.openai.com only accepts the Responses API for its (reasoning)
        models when tools + reasoning are in play (chat/completions 400s).
      - api.anthropic.com / ``…/anthropic`` suffixes speak native Messages.
      - Kimi's ``/coding`` endpoint speaks native Messages.
      - AWS Bedrock runtime hosts speak Converse.

    These are *mandatory* — a session carrying a stale api_mode (e.g. a
    /model switch that kept the previous provider's ``chat_completions``)
    must be overridden to the host's required mode, not merely filled in
    when empty. Generic / unknown endpoints return None so an explicitly
    configured api_mode on them is never clobbered.
    N/zapi.kimi.comz/codingr9   zapi.anthropic.comz
/anthropiczapi.openai.comr*   zbedrock-runtime.zamazonaws.comrj   )rstripr   r   endswithr   r
   )rs   	url_lowerhostnames      r"   host_mandated_api_moder   (  s      $**,I *H >!i9&<#&&)*<*<\*J### -.3HSb3c!r!   c                    t        |      }||S t        |       }| t        j                  |j                  d      S | dk(  ryy)u<  Determine the API mode (wire protocol) for a provider/endpoint.

    Resolution order:
      1. Host-mandated mode (special endpoints that only accept one protocol).
      2. Known provider → transport → TRANSPORT_TO_API_MODE.
      3. Direct provider checks (bedrock).
      4. Default: 'chat_completions'.
    r   rl   rj   )r   r   r   r   r   )r   rs   mandatedr   s       r"   determine_api_moder   J  sQ     &h/H!D$((9KLL 9!r!   c           
        |rt        |t              sy|j                  |       }t        |t              sy|j                  dd      xs | }|j                  dd      xs* |j                  dd      xs |j                  dd      xs d}|j                  dd      xs d}|j                  dd	      xs d	}g }|r|j                  |       t	        | ||t        |      |d
dd      S )zResolve a provider from the user's config.yaml ``providers:`` section.

    Args:
        name: Provider name as given by the user.
        user_config: The ``providers:`` dict from config.yaml.

    Returns:
        ProviderDef if found, else None.
    Nrq   r   r   urlrs   key_envr   r   Fr   user-configrp   rq   r   rr   rs   r   r   ru   )
isinstancedictr   r   ro   r   )rq   user_configentrydisplay_nameapi_urlr   r   r   s           r"   resolve_user_providerr   d  s     jd;OOD!EeT" 99VR(0DLiir"]eiir&:]eii
TV>W][]Gii	2&,"G		+}5FIH x	 	r!   c                d    d| j                         j                         j                  dd      z   S )zBuild a canonical slug for a custom_providers entry.

    Matches the convention used by runtime_provider and credential_pool
    (``custom:<normalized-name>``).  Centralised here so all call-sites
    produce identical slugs.
    r    -)r   r   replace)r   s    r"   custom_provider_slugr     s.     |))+113;;CEEEr!   c                   |rt        |t              sy| xs dj                         j                         }|sy|dk(  }d}|D ]  }t        |t              s|j                  d      xs dj                         }|j                  dd      xs* |j                  dd      xs |j                  dd      xs dj                         }|r|s|j                  d      xs dj                         }g }	|r|	j                  |       |||t        |	      f}t        |      }
||j                         |
hvrt        |
|d	t        |	      |d
dd      c S  |r&|r$|\  }}}t        |      }
t        |
|d	||d
dd      S y)zIResolve a provider from the user's config.yaml ``custom_providers`` list.Nr   r   rq   rs   r   r   r   r   Fr   r   r   )
r   r   r   r   r   r   r   r   r   ro   )rq   custom_providers	requestedbare_custom_fallbackfirst_validr   r   r   r   r   slugdnameaurldenvs                 r"   resolve_custom_providerr     s   
 :.>#E""$**,I
 %0>BK! $
%&		&)/R668IIj"% yy#yy# 
%' 	 799Y'-2446 OOG$ '%/BK#L1\//1488#"8_ 	
 		
7$
N 'tT#E*#! 	
 		
 r!   c           	        t        |       }| j                         j                         }|rt        ||      }||S ||k7  r	 ddlm} |j                  |      }|u|D cg c]  }t        |      |k(  r| }	}t        |	      dkD  rJt        |j                  |j                  dt        |j                  xs d      |j                  xs dd	      S t        |      }
|
|
S |r t        ||      }||S t        ||      }||S t!        | |      }||S 	 dd
lm}  ||      }|/t        ||j                  d|j&                  |j(                  d	      S 	 yc c}w # t        $ r Y w xY w# t        $ r Y yw xY w)u  Full resolution chain: built-in → models.dev → user config.

    This is the main entry point for --provider flag resolution.

    Args:
        name: Provider name or alias.
        user_providers: The ``providers:`` dict from config.yaml (optional).
        custom_providers: The ``custom_providers:`` list from config.yaml (optional).

    Returns:
        ProviderDef if found, else None.
    Nr   )PROVIDER_REGISTRY   r   r   r   zhermes-auth-registry)rp   rq   r   rr   rs   ru   r   r   )r   r   r   r   hermes_cli.authr   r   lenro   rp   rq   r   rr   inference_base_urlr   r   r   r   r   r   r   )rq   user_providersr   r   raw	user_pdef_AUTH_PROVIDER_REGISTRY_pcfg_rid_collapsed_siblingsr   custom_pdefr   r   s                 r"   resolve_provider_fullr     s   " #4(I
**,


C )#~>	  C	T+//4E  !8')$/9< '# '
 *+a/& 88"ZZ"/).u/E/E/K)L!&!9!9!?R5  	"D ))^D	 )#~>	  *$0@AKH"9-	 ^^'!*"#  ! m'  		J  s7   E E6AE >E' E 	E$#E$'	E32E3)rq   r   returnr   )rq   r   r   Optional[ProviderDef])r   r   r   r   )r   r   r   r   )r   )rs   r   r   zOptional[str])r   r   rs   r   r   r   )rq   r   r   zDict[str, Any]r   r   )r   r   r   r   )rq   r   r   Optional[List[Dict[str, Any]]]r   r   )NN)rq   r   r   zOptional[Dict[str, Any]]r   r   r   r   )&r   
__future__r   loggingdataclassesr   typingr   r   r   r   r	   utilsr
   r   	getLoggerr   loggerr   rm   r    ro   r   r   r   r   r   r   r   	frozensetr   r   r   r   r   r   r   r   r   r!   r"   <module>r     sv	  & #  ! 3 3 :			8	$ $  s-	='s- -.s- M%Es-  M#"A!s-* -#5*+s-4 #"/'	5s-@ -"5/	As-L &4&Ms-Z =#$)/	[s-f m;gs-n &Eos-v 
=E'ws-@ }(As-H }+?+	Is-T }&+Us-\ ]&"<]s-f -&.gs-n ,os-v }-ws-~ =7s-F 0Gs-P =/Qs-Z M,[s-d =&es-n m*os-x 
=#/'ys-B m?*Cs-L m*Ms-T ,Us-\ ]7)]s-f 
=':'	gs-r -Ass-| }+5+	}s-H M1*Is-V #1 $_s-) sr   &zlz
 
5z Ez Ez Uz Ez Ez Ez +z z  +!z" k#z( 
8)z* (+z, H-z. /z4 5z6 $7z8 '9z: !;z@ IAzB 9CzH \IzJ ,KzP kQzR ;SzX YzZ [z\ -]zb Jczd 
:ezj 	-kzl }mzr szt uzv Fwz| }zB CzD iEzF IGzH YIzJ +KzL +MzN 0OzT 	-UzV MWzX }Yz^ _z` azf Hgzh 8izn !ozp "qzr 'szt %uzz 
9{z| 9}z~ iz@ iAzF GzH wIzN OzP QzV KWzX 	+Yz^ Y_zd 
ezf gzh sz zD "'"*"8$ . * &.(*	) ~ !CL$1& -67 - > ($D4$NFG
G4G GX 047;d
d,d 5d 	dr!   