
     Yj}                   r   d Z ddlmZ ddlZddlZddlZddlmZ ddlm	Z	m
Z
mZ  ej        e          ZddlmZ ddlmZmZmZmZmZ ddlmZ dd	lmZmZmZmZm Z m!Z!m"Z"m#Z#m$Z$m%Z%m&Z&m'Z'm(Z(m)Z)m*Z*m+Z+ dd
l,m-Z-m.Z.m/Z/ ddl0m1Z1 ddl2m3Z3m4Z4m5Z5 dZd[dZ6d\dZ7d]dZ8d^dZ9d_dZ:d`d Z;dad!Z<dbd"Z=dad#Z>dcd$Z?ddded'Z@dfd)ZAh d*ZBdgd-ZCdhd.ZDdid1ZEdddd2djd9ZFdddkd;ZG	 	 dldmd?ZHdndBZIdndCZJdodDZKdpdEZLd_dFZMdddGdqdIZNdhdJZOdrdLZPdddMdsdPZQdddMdtdQZRddddRdudSZSdddMdvdTZTdddddUdwdVZUdxdYZVdS )yzGShared runtime provider resolution for CLI, gateway, cron, and helpers.    )annotationsN)urlparse)AnyDictOptional)auth)CredentialPoolPooledCredential credential_pool_matches_providerget_custom_provider_pool_key	load_pool)
get_secret)	AuthErrorDEFAULT_CODEX_BASE_URLDEFAULT_QWEN_BASE_URLDEFAULT_XAI_OAUTH_BASE_URLPROVIDER_REGISTRY_agent_key_is_usable_nous_inference_env_overrideformat_auth_errorresolve_provider resolve_nous_runtime_credentials!resolve_codex_runtime_credentials%resolve_xai_oauth_runtime_credentials resolve_qwen_runtime_credentials$resolve_api_key_provider_credentials-resolve_external_process_provider_credentialshas_usable_secret)get_compatible_custom_providersload_confignormalize_extra_headers)OPENROUTER_BASE_URL)base_url_host_matchesbase_url_hostnameenv_int namestrdefaultreturnc                .    t          | |          }||n|S )a  Profile-scoped replacement for ``os.getenv`` on credential/provider reads.

    Routes through the secret scope (Workstream A): identical to ``os.getenv``
    when multiplexing is off, scope-aware (and fail-closed on an unscoped read)
    when on. Genuinely-global vars are handled inside ``get_secret`` and still
    read ``os.environ``. Keeps the ``(name, default) -> str`` contract every
    call site here already relies on.
    )_get_secret)r'   r)   vals      PC:\Users\server\AppData\Local\hermes\hermes-agent\hermes_cli\runtime_provider.py_getenvr/   1   s!     dG
$
$C/33w.    valuec                v    |                                                                                      dd          S )N -)striplowerreplacer1   s    r.   _normalize_custom_provider_namer9   >   s,    ;;==  ((c222r0   hostboolc                \    | pd                                                     d          }|dv S )Nr&   .>   ::10.0.0.0	localhost	127.0.0.1)r6   rstrip)r:   hs     r.   _loopback_hostnamerD   B   s1    	##C((A<<<r0   cfg_base_urlcfg_providerc                D   |pd                                                                 }| pd                                 }|sdS |dk    rdS 	 ddlm}  ||          dk    rdS n# t          $ r Y nw xY wt          |d          rdS t          t          |                    S )u  Decide whether ``model.base_url`` may back bare ``custom`` runtime resolution.

    GitHub #14676: the model picker can select Custom while ``model.provider`` still reflects a
    previous provider. Reject non-loopback URLs unless the YAML provider is already ``custom``
    (or one of the local-server aliases that resolve to ``custom`` — ollama, vllm, llamacpp, …),
    so a stale OpenRouter/Z.ai base_url cannot hijack local ``custom`` sessions.
    r&   FcustomTr   r   openrouter.ai)r5   r6   hermes_cli.authr   	Exceptionr#   rD   r$   )rE   rF   cfg_provider_normbu_resolve_providers        r.   ,_config_base_url_trustworthy_for_bare_customrP   G   s     &+2244::<<

"	#	#	%	%B uH$$t
IIIIII.//8;;4 <   R11 u/33444s   A$ $
A10A1base_urlOptional[str]c                   | pd                                                                                     d          }t          |           }|dk    rdS |dk    rdS |dk    rdS t	          |          j                            d          }|                    d          s|                    d	          rdS |d
k    rd|v rdS dS )u^  Auto-detect api_mode from the resolved base URL.

    - Direct api.openai.com endpoints need the Responses API for GPT-5.x
      tool calls with reasoning (chat/completions returns 400).
    - Direct api.anthropic.com endpoints must use the native Messages
      API (``/v1/messages``).  Anthropic also exposes an OpenAI-compat
      ``/chat/completions`` shim on the same host, but Pro/Max OAuth
      subscriptions are only billed against the native Messages route;
      hitting the shim accounts against a separate "extra usage" pool
      that is empty by default and surfaces as HTTP 400 "You're out of
      extra usage."  See issue #32243.
    - Third-party Anthropic-compatible gateways (MiniMax, Zhipu GLM,
      LiteLLM proxies, etc.) conventionally expose the native Anthropic
      protocol under a ``/anthropic`` suffix — treat those as
      ``anthropic_messages`` transport instead of the default
      ``chat_completions``.
    - Kimi Code's ``api.kimi.com/coding`` endpoint also speaks the
      Anthropic Messages protocol (the /coding route accepts Claude
      Code's native request shape).
    r&   /zapi.x.aicodex_responseszapi.openai.comapi.anthropic.comanthropic_messagesz
/anthropicz/anthropic/v1zapi.kimi.comz/codingN)r5   r6   rB   r$   r   pathendswith)rQ   
normalizedhostnamerX   s       r.   _detect_api_mode_for_urlr\   e   s    * .b''))//1188==J **H:  ###  
 &&&##J$++C00D}}\"" $dmmO&D&D $##>!!i:&=&=##4r0   	model_cfgDict[str, Any]c                    t          |                     d                    }t          |          }|dk    r%|dk    rt                              d|pd           d}|p|pdS )a  Resolve api_mode for legacy/plain ``provider: custom`` endpoints.

    Custom endpoints should stay conservative by default. Only direct OpenAI/xAI
    URLs imply Responses API automatically; named custom providers can opt in via
    their own ``api_mode`` field. This also prevents a stale persisted
    ``model.api_mode: codex_responses`` from forcing generic relays onto the
    Responses path after upgrades or /reset.
    api_moderU   zMIgnoring persisted custom api_mode=codex_responses for non-OpenAI endpoint %sz	(unknown)Nchat_completions)_parse_api_modegetr\   loggerinfo)r]   rQ   configured_modedetected_modes       r.   _resolve_plain_custom_api_moderh      sz     &immJ&?&?@@O,X66M+++AR0R0R[#	
 	
 	
 AmA/AAr0   c                r   t          |           }|sdS t          d |                    d          d         D                       rdS |dv sd|v rdS d |                    d          D             }|r+|d         d	v r!|                    d           |r
|d         d	v !t	          |          d
k     rdS |d         }d                    d |D                                                       }|r|d                                         sdS |dv rdS | d}t          |d          pd	                                S )u_  Look up `<VENDOR>_API_KEY` in the env, derived from the base URL host.

    Examples:
        https://api.deepseek.com/v1   → DEEPSEEK_API_KEY
        https://api.groq.com/openai/v1 → GROQ_API_KEY
        https://api.mistral.ai/v1     → MISTRAL_API_KEY
        https://generativelanguage.googleapis.com/v1beta/openai/ → GOOGLEAPIS_API_KEY

    Returns the env value (stripped) or "". Never returns env vars whose names
    are already explicitly checked elsewhere — those are handled by their own
    host-gated paths (OPENAI/OPENROUTER/OLLAMA).

    The vendor label is the *registrable* portion of the hostname: strip
    ``api.`` / ``www.`` prefixes, then take the second-to-last label
    (``api.deepseek.com`` → ``deepseek``). Falls back to "" for hostnames
    that don't yield a usable vendor label (IPs, loopback, single-label
    hosts).
    r&   c              3  >   K   | ]}|                                 V  d S N)isdigit.0chs     r.   	<genexpr>z(_host_derived_api_key.<locals>.<genexpr>   s*      
:
:B2::<<
:
:
:
:
:
:r0   r=   )r@   :c                    g | ]}||S  rt   )rn   lbls     r.   
<listcomp>z)_host_derived_api_key.<locals>.<listcomp>   s    888cC8c888r0   r   )apiwww   c              3  F   K   | ]}|                                 r|nd V  dS )_N)isalnumrm   s     r.   rp   z(_host_derived_api_key.<locals>.<genexpr>   s3      EEbjjll3EEEEEEr0   )OPENAI
OPENROUTEROLLAMA_API_KEY)
r$   anysplitpoplenjoinupperisalphar/   r5   )rQ   r[   labelsvendor	sanitizedenv_names         r.   _host_derived_api_keyr      sv   & !**H r

:
:(.."5"5b"9
:
:
::: r>!!SH__r88X^^C00888F
 VAY.00

1  VAY.00
6{{Qr BZFEEfEEEEEKKMMI IaL0022 r666r%%%HHb!!'R..000r0   c                D   | pd                                 }|sdS t          |          pd                                }|sdS |dk    s*|                    d          s|                    d          rdS |                    d          rdS t	          |          dk    rdS dS )	u  Decide whether a configured ``model.base_url`` may back native Anthropic.

    Native ``provider: anthropic`` resolution honors ``model.base_url`` so users
    can point at Anthropic-compatible endpoints (official Anthropic/Claude hosts,
    Azure Foundry, MiniMax/Zhipu/LiteLLM-style ``/anthropic`` proxies, Kimi's
    ``/coding`` route). But a config can carry a *stale* non-Anthropic URL — e.g.
    ``provider: anthropic`` left with ``base_url: https://openrouter.ai/api/v1``
    after a provider switch — which would route Anthropic OAuth/setup-token
    traffic to an OpenAI-compatible aggregator and 404. Ignore those.

    Returns True only when the URL plausibly speaks the Anthropic Messages
    protocol; otherwise the caller falls back to ``https://api.anthropic.com``.
    r&   FrV   z.anthropic.comz.claude.comTz
.azure.comrW   )r5   r$   r6   rY   r\   )rQ   	candidater[   s      r.   _anthropic_base_url_override_okr      s     R&&((I u!),,299;;H u &&&(*;*;<L*M*M&QYQbQbcpQqQq&t&& t  	**.BBBt5r0   c                   | sdS 	 ddl }|                     d          }|                    d          s|dz  }|                    |dz   d          }|j        r[|                                                    d	g           }t          |          d
k    r |d                             dd          }|r|S n3# t          $ r&}t          	                    d| |           Y d}~nd}~ww xY wdS )zFQuery a local server for its model name when only one model is loaded.r&   r   NrT   z/v1z/models   )timeoutdata   idz$Auto-detect model from %s failed: %s)
requestsrB   rY   rc   okjsonr   rL   rd   debug)rQ   r   urlrespmodelsmodel_idexcs          r.   _auto_detect_local_modelr     s    rLooc""||E"" 	5LC||C)OQ|777 	$YY[[__VR00F6{{a!!9==r22 $#O L L L 	;XsKKKKKKKKL 2s   B.B6 6
C& C!!C&c                 r   t                      } |                     d          }t          |t                    rt          |          }|                    d          s |                    d          r|d         |d<   |                    d          pd                                }|                    d          pd                                }d|v pd|v }| }|r|r|rt          |          }|r||d<   |S t          |t                    r*|                                rd|                                iS i S )Nmodelr)   r&   rQ   r@   rA   )r    rc   
isinstancedictr5   r   r(   )configr]   cfgr)   rQ   is_localis_fallbackdetecteds           r.   _get_model_configr     sB   ]]F

7##I)T"" 9oowwy!! 	*cggg&6&6 	* \C	N779%%+2244GGJ''-24466(*EkX.E!k 	* 	* 	*/99H *!)I
)S!! .ioo&7&7 .9??,,--Ir0   providerconfigured_providerc                    | pd                                                                 }|pd                                                                 }|sdS |dk    r|dk    p|                    d          S ||k    S )aT  Check whether a persisted api_mode should be honored for a given provider.

    Prevents stale api_mode from a previous provider leaking into a
    different one after a model/provider switch.  Only applies the
    persisted mode when the config's provider matches the runtime
    provider (or when no configured provider is recorded).
    r&   TrH   custom:)r5   r6   
startswith)r   r   normalized_providernormalized_configureds       r.   $_provider_supports_explicit_api_moder   /  s     $>r002288::06B==??EEGG  th&&$0_4I4T4TU^4_4__ $777r0   api_keyc                   t          |                     d          pd                                                                          }t	          |                     d                    }|rt          d|          r|S t          |                     d          pd                                          }|sdS 	 ddlm}  |||	          S # t          $ r Y dS w xY w)
Nr   r&   r`   copilotr)   ra   r   )copilot_model_api_mode)r   )	r(   rc   r5   r6   rb   r   hermes_cli.modelsr   rL   )r]   r   r   rf   
model_namer   s         r.   _copilot_runtime_api_moder   @  s    immJ77=2>>DDFFLLNN%immJ&?&?@@O ?	K^__ Y]]9--344::<<J "!!"<<<<<<%%j'BBBB " " "!!!"s   :C 
CC>   rU   bedrock_conversera   codex_app_serverrW   rawr   c                    t          | t                    r1|                                                                 }|t          v r|S dS )z@Validate an api_mode value from config. Returns None if invalid.N)r   r(   r5   r6   _VALID_API_MODES)r   rZ   s     r.   rb   rb   `  sD    #s YY[[&&((
)))4r0   c                 "    t                      pdS )uV  Return the trusted Nous runtime base URL override, if configured.

    Delegates to ``auth._nous_inference_env_override`` so every
    ``NOUS_INFERENCE_BASE_URL`` read shares one normalization path
    (trailing-slash stripping, blank → empty). The env source is trusted
    and intentionally bypasses the network host allowlist there.
    r&   )r   rt   r0   r.   !_nous_inference_base_url_overrider   i  s     ())/R/r0   r`   Optional[Dict[str, Any]]c                    |s|S | dvr|S t          |                    d          pd                                                                          }|dk    rdS |S )u  Optional opt-in: rewrite api_mode → "codex_app_server" for OpenAI/Codex
    providers when the user has explicitly enabled that runtime via
    `model.openai_runtime: codex_app_server` in config.yaml.

    Default behavior is preserved: when the key is unset, "auto", or empty,
    this function is a no-op. Only providers in {"openai", "openai-codex"}
    are eligible — other providers (anthropic, openrouter, etc.) cannot be
    rerouted through codex.

    Returns the (possibly-rewritten) api_mode.>   openaiopenai-codexopenai_runtimer&   r   )r(   rc   r5   r6   )r   r`   r]   runtimes       r.   %_maybe_apply_codex_app_server_runtimer   t  sp       111)-- 0117R88>>@@FFHHG$$$!!Or0   )r]   pooltarget_modelentryr
   requested_providerr   Optional[CredentialPool]r   c           	     	   |pt                      }|p|                    d          pd}t          |dd           pt          |dd           pd                    d          }t          |dd           pt          |dd          }d}	| d	k    rd
}	|pt          }n| dk    rd
}	|pt
          }n| dk    rd}	|pt          }n| dk    r%d}	t          j        |           }
|p
|
r|
j        nd}n| dk    rd}	t          |                    d          pd          
                                                                }d}|dk    rZt          |                    d          pd          
                                                    d          }t          |          sd}|p|pd}n| dk    r|pt          }n| dk    rd
}	n| dk    rd}	t                      p|}n| dk    r5t          |t          |dd                    }	|pt          d         j        }n\| dk    rt          |                    d          pd          
                                                                }|dk    rst          |                    d          pd          
                                                    d          }|r|}t!          |                    d                    }|r|}	|r/|	dk    r)	 ddlm}  ||          }n# t&          $ r d }Y nw xY w|r|}	|	dk    rt)          j        dd|          }nEt          |                    d          pd          
                                                                }t          j        |           }
|
o0|                    d          |
j                            d          k    }|| k    rO|rMt          |                    d          pd          
                                                    d          }|r|}t!          |                    d                    }| dv rddlm}  || |          }	n(|rt/          | |          r|}	nt1          |          }|r|}	| dv rddlm}  || |	|          }t5          | |	|          }	| dk    rt7          j        |          }| |	||t          |d d!          ||d"S )#Nr)   r&   runtime_base_urlrQ   rT   runtime_api_keyaccess_tokenra   r   rU   	xai-oauth
qwen-oauthminimax-oauthrW   	anthropicr   https://api.anthropic.com
openrouterxainousr   azure-foundryr`   r   azure_foundry_model_api_mode/v1/?$   opencode-goopencode-zenopencode_model_api_modenormalize_opencode_base_url)r   r`   r]   lmstudiosourcer   )r   r`   rQ   r   r   credential_poolr   )r   rc   getattrrB   r   r   r   r   inference_base_urlr(   r5   r6   r   r"   r   r   rb   r   r   rL   resubr   r   r\   r   r   auth_mod$_normalize_lmstudio_runtime_base_url)r   r   r   r]   r   r   effective_modelrQ   r   r`   pconfigrF   rE   rf   r   inferredr   pool_url_is_defaultr   r   r   s                        r.    _resolve_runtime_from_pool_entryr     s    0.00I $Ey}}Y'?'?E2O1488bGE:W[<\<\b`bjjknooHe.55[XZ9[9[G!H>!!$55	[	 	 $99	\	!	!%44	_	$	$
 (#'11Ng M : :2	[	 	 '9==44:;;AACCIIKK;&&y}}Z88>B??EEGGNNsSSL2<@@ "!J8J/J	\	!	!22	U		$	V		%466B(	Y		,YGXZ\8]8]^^N0;N	_	$	$9==44:;;AACCIIKK?**y}}Z88>B??EEGGNNsSSL ('-immJ.G.GHHO +*
  	$x+??? JJJJJJ77HH        $#+++viX66H!)--
";";"ArBBHHJJPPRR
 $'11%h(//#*>*>'B\BcBcdgBhBh*h(**/B*y}}Z88>B??EEGGNNsSSL ('))--
*C*CDD666 BAAAAA..xIIHH 	$!EhPc!d!d 	$&HH
 099H $# 222AAAAAA..x8LL 5H	  H :@JJ %6220  s   $K6 6LL	requestedc                   | r:|                                  r&|                                                                  S t                      }|                    d          }t	          |t
                    r:|                                 r&|                                                                 S t          dd                                                                           }|r|S dS )z=Resolve provider request from explicit arg, config, then env.r   HERMES_INFERENCE_PROVIDERr&   auto)r5   r6   r   rc   r   r(   r/   )r   r]   rF   env_providers       r.   resolve_requested_providerr     s     )Y__&& )  &&(((!##I==,,L,$$ ,););)=)= ,!!##))+++ 6;;AACCIIKKL 6r0   provider_labelapi_mode_overrideprovider_namec                P   t          | |          }|sdS 	 t          |          }|                                sdS |                                }|dS t	          |dd          pt	          |dd          }|sdS ||pt          |           pd| |d| |dS # t          $ r Y dS w xY w)	zXCheck if a credential pool exists for a custom endpoint and return a runtime dict if so.r   Nr   r   r&   ra   zpool:)r   r`   rQ   r   r   r   )r   r   has_credentialsselectr   r\   rL   )rQ   r   r   r   pool_keyr   r   pool_api_keys           r.   _try_resolve_from_custom_poolr  0  s     ,HMRRRH t""##%% 	4=4u&7>>d'%Q_acBdBd 	4&)e-Eh-O-OeSe #(h((#
 
 	
    tts"   #B B $B :B 
B%$B%resultNonec                    dD ]:}|                      |          }t          |t                    r|dk    r||d<    dS ;dS )aq  Propagate a per-provider output cap onto the resolved runtime dict.

    Accepts ``max_output_tokens`` or ``max_tokens`` on a ``custom_providers``
    entry so a provider block can pin its own output limit. Gateway and CLI
    map this onto ``AIAgent.max_tokens`` only when the top-level
    ``model.max_tokens`` isn't set, so the documented global key still wins.
    )max_output_tokens
max_tokensr   r  N)rc   r   int)r   r  _k_vs       r.   _lift_max_output_tokensr
  P  sY     2  YYr]]b# 	266*,F&'FF	 r0   c                \    t          |                     d                    }|r||d<   dS dS )zCopy a validated ``extra_headers`` dict from a provider entry.

    SECURITY: header values routinely carry credentials (Cloudflare Access
    service tokens, proxy auth, custom bearer schemes). Never log them.
    extra_headersN)r!   rc   )r   r  r  s      r.   _lift_extra_headersr  _  s?     ,EIIo,F,FGGM 0"/0 0r0   c           	     b   t          | pd          }|sd S |dk    rd S |dk    ri|                    d          sT	 t          j        |          }|pd                                                                |k    rd S n# t          $ r Y nw xY wt                      }|                    d          }t          |t                    rE|                                D ]/\  }}t          |t                    st          |          }t          |                    dd          pd                                          }|r"t          |d                                          nd}	|	s7t          |                    dd          pd                                          }	|||d| hv r"|                    d          p+|                    d	          p|                    d
          pd}
|
r|                    d|          |
                                |	|                    dd          d}|                    d          }t          |t                    rt          |          |d<   t          ||           t          |                    d          p|                    d                    }|r||d<   t!          ||           |c S |                    dd          }|r(t          |          }|||d| hv r|                    d          p+|                    d	          p|                    d
          pd}
|
r||
                                |	|                    dd          d}|                    d          }t          |t                    rt          |          |d<   t          ||           t          |                    d          p|                    d                    }|r||d<   t!          ||           |c S 1|                    d          }t          |t                    rt"                              d           d S t'          |          }|sd S |D ]G}t          |t                    s|                    d          }|                    d
          }
t          |t                    rt          |
t                    snt          |          }d| }t          |                    dd          pd                                          }|rt          |          nd}|rd| nd}|||||hvr|                                |
                                t          |                    dd          pd                                          d}t          |                    dd          pd                                          }|r||d<   |r||d<   |                    d          }t          |t                    rt          |          |d<   t          ||           t          |                    d                    }|r||d<   t          |                    dd          pd                                          }|r||d<   t!          ||           |c S d S )Nr&   r   rH   r   	providerskey_envr   rw   r   rQ   r'   default_model)r'   rQ   r   r   
extra_bodyr`   	transportcustom_providerszcustom_providers in config.yaml is a dict, not a list. Each entry must be prefixed with '-' in YAML. Run 'hermes doctor' for details.provider_key)r'   rQ   r   r   )r9   r   r   r   r5   r6   r   r    rc   r   r   itemsr(   r/   r  rb   r
  rd   warningr   )r   requested_norm	canonicalr   r  ep_namer   	name_normr  resolved_api_keyrQ   r  r  r`   display_namedisplay_normr  r'   menu_keyr  provider_key_normprovider_menu_keyr   s                          r.   _get_named_custom_providerr"  j  s   45G5M2NNN t" t!!.*C*CI*N*N!	 1.AAI R&&((..00NBBt C  	 	 	D	 ]]F 

;''I)T"" =&'oo// <	& <	&NGUeT** 7@@I%))Ir228b99??AAG?FNww3399;;;B# O#&uyyB'?'?'E2#F#F#L#L#N#N '96K	6K6K!LLL 99U++^uyy/?/?^599ZCXCX^\^ " %		&' : :$,NN$4$4#3!&?B!?!?	 F "'<!8!8J!*d33 @/3J/?/?|,'v666  /uyy/D/D/^		R]H^H^__H 6-5z*+E6:::!MMM 99VR00L &>|LL!lLBZLBZBZ%[[[$yy//b599U3C3CbuyyQ[G\G\b`bH &$0(0(8(8'7%*YY%C%C	" " &+YY|%<%<
%j$77 D37
3C3CF<0+E6:::#2599Z3H3H3bEIIVaLbLb#c#c# :19F:./v>>>% zz"455"D)) /	
 	
 	

 t6v>> t! # #%&& 	yy  99Z(($$$ 	Jx,E,E 	3D99	(Y((599^R88>B??EEGGMYa;LIII_a=NV9&7999TV)X7HJ[!\\\JJLL ((599Y339r::@@BB
 

 eii	2..4"55;;== 	( 'F9 	2%1F>"YY|,,
j$'' 	4#'
#3#3F< E6***"599Z#8#899 	*!)F:7B//5266<<>>
 	)(F7Ov...4s   A= =
B
	B
c                H    	 t          |           duS # t          $ r Y dS w xY w)u~  Return True when config defines a custom provider matching the request.

    Thin public wrapper around :func:`_get_named_custom_provider` so other
    modules (e.g. the cronjob tool) can decide whether a provider name will
    actually resolve to a configured ``providers:`` / ``custom_providers:``
    entry — without reaching into a private helper or duplicating the scan.
    NF)r"  rL   )r   s    r.   has_named_custom_providerr$  
  s=    )*<==TII   uus    
!!c                ~   t          |           }|sdS 	 t                      }n# t          $ r Y dS w xY w|                    d          }t	          |t
                    r|                                D ]\  }}t	          |t
                    s|                    d          p+|                    d          p|                    d          pd}t          |          |k    r!dt          t          |                     c S 	 t          |          }n# t          $ r d}Y nw xY w|pg D ]}t	          |t
                    s|                    d          }t	          |t                    r|
                                sWt          |                    d                    |k    rdt          |           c S dS )	uD  Map an endpoint URL back to its canonical ``custom:<name>`` menu key.

    Returns the ``custom:<normalized-name>`` slug of the first ``providers:``
    / ``custom_providers:`` entry whose base_url matches, or ``None`` when no
    entry owns the URL.

    Session persistence stores the agent's *resolved* provider, and for every
    named custom endpoint that is the literal string ``"custom"`` — the entry
    name is lost, and the api_key is deliberately never persisted. The
    endpoint URL is the one durable fact that survives the round-trip, so
    this reverse lookup lets persist/rebuild paths recover the entry identity
    (and with it key_env/api_key/api_mode resolution via
    :func:`_get_named_custom_provider`) instead of failing with
    ``auth_unavailable`` or silently rebuilding with placeholder credentials.
    Nr  rw   r   rQ   r&   r   r'   )_normalize_base_url_for_matchr    rL   rc   r   r   r  r9   r(   r   r5   )	rQ   targetr   r  r  r   	entry_urlr  r'   s	            r.   find_custom_provider_identityr)    s
     +844F t   tt 

;''I)T"" Q'oo// 	Q 	QNGUeT** 		%  SEIIe$4$4S		*8M8MSQS  -Y776AAP!@W!N!NPPPPP B :6BB       !'R E E%&& 	yy  $$$ 	DJJLL 	(:)>)>??6IID<TBBDDDDD J 4s   $ 
22D D$#D$)rQ   config_providerr*  c                6   | rt          |           }|r|S t          |pd                                          }|sV	 t          t                                          d          pd                                          }n# t
          $ r d}Y nw xY w|s2t          j                            dd                                          }t          |          }|r|dv rdS 	 t          |          |
                    d          r|S d| S n# t
          $ r Y nw xY wdS )u  Recover a routable ``custom:<name>`` identity for a bare custom provider.

    The bare string ``"custom"`` is the *resolved billing class* shared by
    every named ``providers:`` / ``custom_providers:`` entry — it is NOT a
    routable provider identity (``resolve_runtime_provider("custom")`` falls
    through to the OpenRouter default URL with no api_key, which surfaces to
    the user as "No LLM provider configured").

    Any code path that persists or restores a session's provider override
    must run the resolved provider through this helper so a bare ``"custom"``
    is upgraded back to its durable ``custom:<name>`` menu key. Two recovery
    sources, in priority order:

    1. ``base_url`` — reverse-lookup the entry that owns the endpoint URL
       (the one fact that always survives the persistence round-trip when a
       URL was recorded).
    2. ``config_provider`` — the active ``config.model.provider`` (or its
       ``provider``/``HERMES_INFERENCE_PROVIDER`` equivalent). When the agent
       was built without a base_url on the override (the recurring
       Desktop/TUI regression vector), the configured provider is the only
       durable identity left, so fall back to it when it names a real entry.

    Returns ``custom:<name>`` when a routable identity is recovered, else
    ``None`` (caller keeps whatever it had — bare ``"custom"`` only as a last
    resort, e.g. a genuine ad-hoc endpoint with no config entry).
    r&   r   r   >   r   rH   r   Nr   )r)  r(   r5   r   rc   rL   osenvironr9   r"  r   )rQ   r*  identityr   candidate_norms        r.   canonical_custom_identityr0  K  sf   @  0:: 	O O)r**0022I 	-//33J??E2FFLLNNII 	 	 	III	 LJNN#>CCIIKK	4Y??N ^/OOOt%i00<((33 &%%-^--- =    4s*   AA? ?BB%D	 D	 	
DDc                    t          | pd                                                              d                                          S )Nr&   rT   )r(   r5   rB   r6   r8   s    r.   r&  r&    s:    u{!!##**3//55777r0   custom_providerc                    |                      d          }t          |t                    r|si S dt          |          iS )Nr  )rc   r   r   )r2  r  s     r.   "_custom_provider_request_overridesr4    sF     $$\22Jj$'' z 	$z**++r0   explicit_api_keyexplicit_base_urlr6  r7  c           
     	   | pd                                                                 }|r/|dk    r)	 ddlm}  ||          dk    rd}n# t          $ r Y nw xY w|dk    r|r|                                                     d          }t          |dd           }|rd|d<   |S t          |d          pt          |d	          }t          |d
          }|pd                                 |r"t          dd                                           nd|r"t          dd                                           ndt          |          g}	t          d |	D             d          pd}
dt          |          pd||
d| dS t          |           }|sd S |pd                                 p|                    dd                              d          }|sd S t          |d|                    d          |                    d                    }|r|                    d          }|r||d<   t          |                    d          t                    r|d         |d<   t!          |          }|r+i t#          |                    d          pi           ||d<   |                    d          rt#          |d                   |d<   |S t          |d          pt          |d	          }t          |d
          }|pd                                 t%          |                    dd          pd                                           t          t%          |                    dd          pd                                           d                                           |r"t          dd                                           nd|r"t          dd                                           ndt          |          g}	t          d |	D             d          }
d|                    d          pt          |          pd||
pdd|                    d|            d}|                    d          r|d         |d<   t          |                    d          t                    r|d         |d<   |                    d          rt#          |d                   |d<   t!          |          }|r||d<   |S )Nr&   rH   r   rI   rT   zdirect-aliasr   
openai.comopenai.azure.comrJ   OPENAI_API_KEYOPENROUTER_API_KEYc              3  8   K   | ]}t          |          |V  d S rk   r   )rn   cs     r.   rp   z0_resolve_named_custom_runtime.<locals>.<genexpr>  s0      CC1.?.B.BCQCCCCCCr0   no-key-requiredra   r   r`   rQ   r   r   r   rQ   r`   r'   r   r   r  request_overridesr  r   r  c              3  8   K   | ]}t          |          |V  d S rk   r>  rn   r   s     r.   rp   z0_resolve_named_custom_runtime.<locals>.<genexpr>  s1      bb)EVW`EaEabIbbbbbbr0   zcustom_provider:r   r`   rQ   r   r   )r5   r6   rK   r   rL   rB   r  r#   r/   r   nextr\   r"  rc   r   r  r4  r   r(   )r   r6  r7  r  rO   rQ   pool_result_da_is_openai_url_da_is_openrouterapi_key_candidatesr   r2  r   rB  _cp_is_openai_url_cp_is_openrouterr  s                    r.   _resolve_named_custom_runtimerM    s    ).B5577==??N .H44	MMMMMM  00H<<!) 	 	 	D	!!&7!$**,,33C88 4HhMM 	$2K!3HlKK  COdem  pB  PC  PC3HoNN#**,,:KSW%r**00222QS:KTW)2..44666RT "(++	
 CC*CCC
 
   	
 !0::P>P $"4
 
 	
 11CDDO t 
	 b'')) 	/z2..fSkk   t 0(ODWDWXbDcDc  tC  tG  tG  HN  tO  tO  P  P  PK  %((11
 	.#-K o))*=>>DD 	T/>?R/SK+,>OO 	0{':;;ArBB0#0K+, // 	R+/0P+Q+QK(/,GG~K`aik}K~K~//JJ		R&&((O	2..4"55;;==O''	266<"==CCEErJJPPRR 7H	P!2	&	&	,	,	.	.	.b6G	P%r	*	*	0	0	2	2	2b 	h'' bb/AbbbdfggG #''
33 #H--//V_%8%8AS%T%TVV F 7## 3)'2w/%%&9::C@@ K&56I&J"# ?++ I"&'G"H"H:?KK 8&7"#Ms   A
 

AAc           	        t                      }t          |                    d          t                    r|                    d          nd}t          |                    d          t                    r|                    d          nd}d}dD ]V}|                    |          }t          |t                    r*|                                r|                                } nW| pd                                                                }	|                                                                }|	r/|	dk    r)	 ddlm}
  |
|	          dk    rd}	n# t          $ r Y nw xY wt          dd                                          }t          d	d                                          }d
}|                                r+|s)|	dk    r|r|dk    rd}n|	dk    rt          ||          rd}|pd                                p"|p |r|                                ndp|pt                              d          }t          |d          }|p(|	dk    o"|p||k    o||pd                    d          k    }|r |t          d          t          d          g}n~t          |d          }t          |d          }t          |d          }||r|nd|rt          d          nd|s|rt          d          nd|rt          d          ndt          |          g}t          d |D             d          }|s|rdnd}|	dk    rdnd}|dk    rA|r?t!          ||t#          |                    d                    |	dk    r| nd           }|r|S |dk    r|s|sd}||dk    rt%          ||          n2t#          |                    d                    pt'          |          pd|||dS )NrQ   r&   r   )r   rw   rH   r   rI   r"   CUSTOM_BASE_URLFr   TrT   rJ   r   r<  r;  z
ollama.comr9  r:  OLLAMA_API_KEYc              3  z   K   | ]6}t          |          t          |pd                                           V  7dS )r&   N)r   r(   r5   rD  s     r.   rp   z._resolve_openrouter_runtime.<locals>.<genexpr>  sI      jj)M^_hMiMijY_"			#	#	%	%jjjjjjr0   explicitz
env/configr`   r   r@  ra   rE  )r   r   rc   r(   r5   r6   rK   r   rL   r/   rP   r"   rB   r#   r   rF  r  rb   rh   r\   )r   r6  r7  r]   rE   rF   cfg_api_keykvr  rO   env_openrouter_base_urlenv_custom_base_urluse_config_base_urlrQ   _is_openrouter_url_is_openrouter_contextrJ  _is_ollama_url_is_openai_url_is_openai_azurer   r   effective_providerrG  s                            r.   _resolve_openrouter_runtimer_    s    "##I0:9==;T;TVY0Z0Zb9==,,,`bL0:9==;T;TVY0Z0Zb9==,,,`bLK  MM!a 	!'')) 	''))KE(.B5577==??N%%''--//L  .H44	MMMMMM  00H<<!) 	 	 	D	 &&;R@@FFHH!"3R88>>@@
   '$5 'V## +<6#9#9&*#x'',X,-
 -
' #' 
	 b'')) 		$7?L   R	 #	 fSkk  /xII 0 ,& 	D$K4K(K	D06B>>sCCC 
   
())$%%
 2(LII1(LII1(<NOO /7[[R.<ZW%&&&XZ/=ZAQZW%&&&XZ.@ZW)***XZ
 "(++
 jj7Ijjj
 G
 -T0ATZZF &4x%?%?\ X%%(% 4(/)--
:S:S*T*T0>(0J0J,,PT
 
 
  	X%%g%>P%# ')) 39hGGGY]]:6677 #H--
 
 
s   ?E 
E$#E$)r6  r7  r   c           	        t          |pd                                          }t          |pd                                                              d          }t          |                    d          pd                                                                          }d}d}d}	i }
|dk    rt          |                    d          pd                                                              d          }t          |                    d                    pd}t          |                    d	          pd                                                                          pd}	|                    d
          }t          |t                    r|}
t          |p|                    d          pd                                          }|r/|dk    r)	 ddlm	}  ||          }n# t          $ r d}Y nw xY w|r|}t          dd                                                              d          }|p|p|}|st          d          |dk    rt          j        dd|          }|	dk    r|r|}d}d}n	 ddlm}m}m} n&# t          $ r}t          d| d          |d}~ww xY wt          |
                    d          pd                                          p|}	  ||          } ||          }n/# t&          $ r"}t          t          |                    |d}~ww xY w|}d}d}i }|dk    r=t          |
                    d          pd                                          }|r||d<   d||||||| dS |}|s'	 ddlm}  |d          pd}n# t          $ r d}Y nw xY w|s"t          dd                                          }|st          d          |s|rdnd}d|||d|| d S )!a  Resolve an Azure Foundry runtime entry.

    Reads ``model.base_url`` + ``model.api_mode`` from config.yaml (or
    explicit overrides), pulls the API key from ``.env`` / env var, and
    strips a trailing ``/v1`` for Anthropic-style endpoints because the
    Anthropic SDK appends ``/v1/messages`` internally.

    When ``model.auth_mode == "entra_id"`` (and the model is OpenAI-style),
    the returned ``api_key`` is a zero-arg callable produced by
    :func:`agent.azure_identity_adapter.build_token_provider` rather than
    a string. Downstream code that constructs an OpenAI SDK client passes
    this through unchanged (the SDK accepts ``Callable[[], str]`` for
    ``api_key`` and calls it before every request). Code paths that need
    a string (logging, manual HTTP probes, header injection) must use the
    helpers in ``agent.azure_identity_adapter``.

    Raises :class:`AuthError` when required values are missing.
    r&   rT   r   ra   r   r   rQ   r`   	auth_modeentrar)   rW   r   r   NAZURE_FOUNDRY_BASE_URLzpAzure Foundry requires a base URL. Set it via 'hermes model' or the AZURE_FOUNDRY_BASE_URL environment variable.r   entra_idrR  )EntraIdentityConfigSCOPE_AI_AZURE_DEFAULTbuild_token_providerzAzure Foundry Entra ID auth requires the 'azure-identity' package. Install it with: pip install azure-identity (import failed: )scope)ri  )r   )r   r`   rQ   r   ra  rb  r   r   )get_env_valueAZURE_FOUNDRY_API_KEYa  Azure Foundry requires an API key. Set AZURE_FOUNDRY_API_KEY in ~/.hermes/.env or run 'hermes model' to configure. To use keyless Microsoft Entra ID auth instead, set model.auth_mode: entra_id in config.yaml (or pick 'Microsoft Entra ID' in 'hermes model').r   )r   r`   rQ   r   ra  r   r   )r(   r5   rB   rc   r6   rb   r   r   r   r   rL   r/   r   r   r   agent.azure_identity_adapterre  rf  rg  ImportErrorhermes_cli.configrj  )r   r]   r6  r7  r   explicit_base_url_cleanrF   rE   cfg_api_modecfg_auth_mode	cfg_entra_entrar   r   r   env_base_urlrQ   r   r   ra  re  rf  rg  r   ri  entra_configtoken_providerclean_entraconfigured_scoperj  s                                 r.   _resolve_azure_foundry_runtimery    s1   4 +1r2288::!"3"9r::@@BBII#NNy}}Z006B77==??EEGGLL%LM "I&&9==44:;;AACCJJ3OO&y}}Z'@'@AAWEWIMM+66C)DDJJLLRRTTaXaw''fd## 	I ,H)--	*B*BHbIIOOQQO $<+???	FFFFFF33ODDHH 	 	 	HHH	 	$#L3R88>>@@GGLLL&F,F,H 
?
 
 	
 +++6)R22  
"" !	# ,GF!II          
    .'*. . .  	 IMM'**0b117799 *) 322      "6!5\!J!J!J 3 3 3C))s23$GF"I
"""9==#9#9#?R@@FFHH 8'7G$ ($ " "4	
 	
 		
 G 	777777#m$;<<BGG 	 	 	GGG	 ?1266<<>> 
7
 
 	
 -P0APZZF# 0  sT   G& &G54G55
J   
J#
JJ#K8 8
L$LL$N N%$N%c           
     	   t          |pd                                          }t          |pd                                                              d          }|s|sd S | dk    rt          |                    d          pd                                                                          }d}|dk    rZt          |                    d          pd                                                              d          }t          |          sd}|p|pd}|}|s!ddlm}	  |	            }|st          d	          dd
||d|dS | dk    r|pt          }|}d }
|sft                      }|                    dd          }|                    d          }
|s+|                    dd                              d          p|}dd||d|
|dS | dk    rt          j        d          pi }|p`t                      pRt          |                    d          pt          j                                                                      d          }|pct          |t!          dt#          dd                              r6t          |                    d          pd                                          nd}|                    d          p|                    d          }|st%          t'          t)          dd                              }|                    dd          }|                    d          }|s+|                    dd                              d          p|}dd||d||dS | dk    rt+          ||||           S t-          j        |           }|re|j        dk    rYd}|j        r:t)          |j        d                                                              d          }|}|sF| d!v r9t3          |           }|                    dd                              d          }n	|p|j        }|}|sPt3          |           }|                    dd          }|s)|                    dd                              d          }d}| d"k    rt7          ||          }nC| d#k    rd}n:t9          |                    d$                    }|r|}nt;          |          }|r|}| ||                    d          |d|dS d S )%Nr&   rT   r   r   rQ   r   r   resolve_anthropic_tokenNo Anthropic credentials found. Set ANTHROPIC_TOKEN or ANTHROPIC_API_KEY, run 'claude setup-token', or authenticate with 'claude /login'.rW   rR  rA  r   r   last_refreshrU   r   r`   rQ   r   r   r~  r   r   r   <   HERMES_NOUS_MIN_KEY_TTL_SECONDS  	agent_keyagent_key_expires_at
expires_atHERMES_NOUS_TIMEOUT_SECONDS15timeout_secondsra   r   r`   rQ   r   r   r  r   r   )r   r]   r6  r7  >   kimi-codingkimi-coding-cnr   r   r`   )r(   r5   rB   rc   r6   r   agent.anthropic_adapterr|  r   r   r   r   get_provider_auth_stater   DEFAULT_NOUS_INFERENCE_URLr   maxr%   r   floatr/   ry  r   	auth_typebase_url_env_varr   r   r   rb   r\   )r   r   r]   r6  r7  rF   rE   rQ   r   r|  r~  credsstater  r   env_urlr`   rf   r   s                      r.   _resolve_explicit_runtimer  P  s    +1r2288::-344::<<CCCHH $5 t;9==44:;;AACCIIKK;&&y}}Z88>B??EEGGNNsSSL2<@@ "!$SS8S" 	GGGGGG--//G V  
 $,  "4
 
 	
 >!!$>(>" 	M577Eii	2..G 99^44L$ M 99Z44;;C@@LH&)  ("4
 
 	
 6088>B o022o599122Yh6YZZ``bbiijmnn 	 # 
#B A4HHII C		+&&,"--33555
  	 YY566Q%))L:Q:Q
 	M4 %g.KT&R&R S S  E ii	2..G<00J$ M 99Z44;;C@@LH*  $"4
 
 	
 ?""-1-/	
 
 
 	
  #H--G +
7$	11# 	Pg6;;AACCJJ3OOG$ 	A<<<<XFF 99Z44;;C@@"@g&@" 	A8BBEii	2..G A 99Z44;;C@@%y  0GDDHH(HH-immJ.G.GHHO (* 4H== ('H !  ,, "4
 
 	
 4r0   )r   r6  r7  r   c           
       : t          |           }|dk    r	ddddd|dS |pd                                }|dk    rzd|v rv|pd                                pCt          d	d                                          p!t          d
d                                          }dd|                    d          |d|dS |dk    r"t	          |t                      |||          }|S |dv rBddlm}  |            \  }	}
|	r|
st          d          dd|
                    d          |	d|dS t          |||          }|r||d<   |S |s|st                      }t          |                    d          pd                                                                          }t          |                    d          pd                                          ::r:|dv r6d}t          :fd|D                       st          |||          }||d<   |S t          |||          }t                      }t!          |||||          }|r|S |dk    }|dk    rt          |                    d          pd                                                                          }t          |                    d          pd                                          :t          d d                                          }t          d!d                                          }t#          |p|p|          }:r|d"v rd#}t#          |p|          }|d$v o| o| }	 |rt%          |          nd%}n# t&          $ r d%}Y nw xY w|r|                                r|                                }d}|"t-          |d&d%          pt-          |d'd          }|d(k    rO|Lt/          d)t1          d*d+                    }t-          |d,d%          t-          |d-d%          t-          |d.d%          d/}t3          ||          st4                              d0           	 |                                }n4# t&          $ r'}t4                              d1|           d%}Y d%}~nd%}~ww xY w|W|}t-          |d&d%          pt-          |d'd          }t-          |d,d%          t-          |d-d%          t-          |d.d%          d/}|rt3          ||          st4                              d2           d}|K|rIt;          ||t-          |d3d%          pt-          |dd%          pd4          rt=          ||||||5          S |d(k    r	 t?          tA          t          d6d7                    8          }d(d|                    dd                              d          |                    d9d          |                    d:d;          |                    d<          |d=S # t          $ r$ |d>k    r t4          !                    d?           Y nw xY w|d@k    r	 tE                      }d@dA|                    dd                              d          |                    d9d          |                    d:dB          |                    dC          |dDS # t          $ r$ |d>k    r t4          !                    dE           Y nw xY w|dFk    r	 tG                      }dFdA|                    d          pd                    d          ptH          |                    d9d          |                    d:dB          |                    dC          |dDS # t          $ r$ |d>k    r t4          !                    dG           Y nw xY w|dHk    r	 tK                      }dHd|                    dd                              d          |                    d9d          |                    d:dI          |                    dJ          |dKS # t          $ r$ |d>k    r t4          !                    dL           Y nw xY w|dMk    rZtM          j        |          }|rD|j'        dNk    r9ddOl(m)}   |             }|d|d         |d9         |                    d:dP          |dS |dQk    rtU          |          }dQd|                    dd                              d          |                    d9d          |                    dRd          tW          |                    dS          pg           |                    d:dT          |dUS |dk    rt          |                    d          pd                                                                          }d:|dk    rM|                    d          pd                                                    d          :tY          :          sd::pdV}
d|
                                v p:od:                                v }!|!rd}	dWD ]`}"t          |                    |"          pd                                          }#|#r&t          |#d                                          }	|	r na|	s6t          |                    d9          pd                                          }	|	sDt          d	d                                          p!t          d
d                                          }	|	st          dX          n!ddYl-m.}$  |$            }	|	st          dZ          dd|
|	d[|dS |d\k    rdd]l/m0}%m1}&m2}'m3}( |d^v })|)s |%            st          d_d`a          ti                                          d\i           }*|*                    db          pd                                p	 |'            }+ |&            pdc},|*                    ddi           }-d%}.|-                    de          rf|-                    df          rQ|-de         |-df         dg}.|-                    dh          r|-dh         |.di<   |-                    dj          r|-dj         |.dj<   t          |p|                    dk          pd                                          }/t#          tj          j6                            dld                                                    }0 |(|/          r|0sd\ddm|+ dndo|,|+d#|dp}nd\dqdm|+ dndo|,|+|dr}|.r|.|ds<   |S tM          j        |          }|r|j'        d9k    r}to          |          }tq          |                    d9                    s<dt9                    |j:                  }1|1rdu|1 dvnd}2t          dw| dx|2 |dyz          t          |                    d          pd                                                                          }d:||k    r<|                    d          pd                                                    d          ::p(|                    dd                              d          }
d}3|d{k    r%tw          ||                    d9d                    }3n|d|k    rdA}3nt          |                    d          pd                                                                          }4ty          |                    d}                    }5|d~v r+ddl=m>}6 |p|                    dkd          }7 |6||7          }3n(|5rt          ||4          r|5}3nt          |
          }8|8r|8}3|d~v rddl=mA}9  |9||3|
          }
|dk    rt          jC        |
          }
||3|
|                    d9d          |                    d:d[          |dS t          |||          }||d<   |S )a)  Resolve runtime provider credentials for agent execution.

    target_model: Optional override for model_cfg.get("default") when
    computing provider-specific api_mode (e.g. OpenCode Zen/Go where different
    models route through different API surfaces). Callers performing an
    explicit mid-session model switch should pass the new model here so
    api_mode is derived from the model they are switching TO, not the stale
    persisted default. Other callers can leave it None to preserve existing
    behavior (api_mode derived from config).
    moara   zmoa://localzmoa-virtual-providerrA  r&   r   z	azure.comAZURE_ANTHROPIC_KEYANTHROPIC_API_KEYrW   rT   zazure-explicitr   )r   r]   r6  r7  r   )vertexzgoogle-vertexz	vertex-aiz
gcp-vertexvertexair   )get_vertex_configa  Vertex AI credentials could not be resolved. Vertex uses OAuth2 (not a static API key): provide a service-account JSON via GOOGLE_APPLICATION_CREDENTIALS (or VERTEX_CREDENTIALS_PATH) in ~/.hermes/.env, or run 'gcloud auth application-default login' for ADC. Set the GCP project/region under vertex: in config.yaml if they aren't embedded in the credentials. Install the extra with: pip install 'hermes-agent[vertex]'.r  zvertex-oauth)r   r6  r7  r   r   rQ   )r   r&   )rJ   zanthropic.comr9  c              3  8   K   | ]}t          |          V  d S rk   )r#   )rn   r:   rE   s     r.   rp   z+resolve_runtime_provider.<locals>.<genexpr>n  sA         &lD99     r0   r5  )r   r   r]   r6  r7  r   OPENAI_BASE_URLr"   >   r   rH   T>   r   r   Nr   r   r   r  r  r  r  r  ri  )r  r  ri  zINous pool entry agent_key expired/missing, refreshing selected pool entryz"Nous pool entry refresh failed: %szRNous pool entry agent_key still unavailable, falling through to runtime resolutionr   )rQ   )r   r   r   r]   r   r   r  r  r  r   r   portalr  r  r   zUAuto-detected Nous provider but credentials failed; falling through to next provider.r   rU   zhermes-auth-storer~  r  zVAuto-detected Codex provider but credentials failed; falling through to next provider.r   zZAuto-detected xAI OAuth provider but credentials failed; falling through to next provider.r   zqwen-cliexpires_at_ms)r   r`   rQ   r   r   r  r   z@Qwen OAuth credentials failed; falling through to next provider.r   oauth_minimax))resolve_minimax_oauth_runtime_credentialsoauthzcopilot-acpcommandargsprocess)r   r`   rQ   r   r  r  r   r   r   )r  api_key_envzNo Azure Anthropic API key found. Set AZURE_ANTHROPIC_KEY or ANTHROPIC_API_KEY, or point key_env/api_key_env in your config.yaml model section at a custom env var.r{  r}  envbedrock)has_aws_credentialsresolve_aws_auth_env_varresolve_bedrock_regionis_anthropic_bedrock_model>   aws-bedrockamazon-bedrockawsamazonr  zNo AWS credentials found for Bedrock. Configure one of:
  - AWS_ACCESS_KEY_ID + AWS_SECRET_ACCESS_KEY
  - AWS_PROFILE (for SSO / named profiles)
  - IAM instance role (EC2, ECS, Lambda)
Or run 'aws configure' to set up credentials.no_aws_credentials)coderegionzaws-sdk-default-chain	guardrailguardrail_identifierguardrail_version)guardrailIdentifierguardrailVersionstream_processing_modestreamProcessingModetracer)   AWS_BEARER_TOKEN_BEDROCKzhttps://bedrock-runtime.z.amazonaws.comzaws-sdk)r   r`   rQ   r   r   r  bedrock_anthropicr   r   )r   r`   rQ   r   r   r  r   guardrail_configz, z Set r=   z*No usable credentials found for provider 'z'.missing_api_key)r   r  r   r   r`   r   r   r   r   )Dr   r5   r/   rB   ry  r   agent.vertex_adapterr  r   rM  r(   rc   r6   r   r_  r   r  r;   r   rL   r   r   r   r  r%   r   rd   r   try_refresh_currentr   r   r   r  re   r   r   r   r   r   r  rK   r  r   listr   r  r|  agent.bedrock_adapterr  r  r  r  r    r,  r-  r   r   r   api_key_env_varsr   rb   r   r   r   r\   r   r   r   );r   r6  r7  r   r   	_eff_base
_azure_keyazure_runtimer  tokenrQ   custom_runtimer]   rF   _known_cloud_hostsr   r   explicit_runtimeshould_use_poolenv_openai_base_urlrV  has_custom_endpointhas_runtime_overrider   r   r   min_ttl
nous_state	refreshedr   r  r   r  _is_azure_endpointhint_keyenv_varr|  r  r  r  r  is_explicit_bedrock_cfgr  auth_source_grr  _current_model_has_bearer_token	env_nameshintr`   r   rf   r   
_effectiver   r   rE   s;                                                             @r.   resolve_runtime_providerr    s   " 4I>>U""*%-,"4
 
 	
 #(b//11I[(([I-E-E#**,, 8,b1177998*B//5577 	 $,!((--!&"4
 
 	
 _,,61'))-/%
 
 
  ___::::::++--x 		H 		N   !* ,,$"4
 
 	
 3-)+  N
  /A+,  %5 %''	9==44:;;AACCIIKK9==44:;;AACC 	LL88"
     .     
 6'9%5&7  
 1C,-)+  H
 "##I0-)+     ,.O<9==44:;;AACCIIKK9==44:;;AACC%&7<<BBDD")*?"D"D"J"J"L"L" '"'&
 

  	'L,>>>"&#$4$I8IJJ"88 )'')(( 	&5?y"""4    >$$&& >0$77 65."55  v%"3"g&GNNOOG$UK>>(/7Mt(T(T 66 J
 (
G<< &hiii% $ 8 8 : :II  % % %LL!EsKKK $IIIIII% (%E'8$?? >"5."== !
 &-UK%F%F07?UW[0\0\!(!>!>" "J
 $ &+?
G+T+T &LL!uvvv#%L 0E#5t<< uj$77    4!#5#)    6	=4 %g.KT&R&R S S  E #.!IIj"55<<SAA 99Y33))Hh77#ii55&8    	= 	= 	=!V++ KK < = = = = =	= >!!	=577E*-!IIj"55<<SAA 99Y33))H.ABB %		. 9 9&8    	= 	= 	=!V++ KK < = = = = =	= ;	=9;;E'-"YYz228b@@EEcIc 99Y33))H.ABB %		. 9 9&8    	= 	= 	=!V++KK < = = = = =	= <	=466E(.!IIj"55<<SAA 99Y33))Hj99!&?!;!;&8    	= 	= 	=!V++KK < = = = = =	= ?""#'11 
	w(O;;QQQQQQ==??E$0!*- +))Hg66&8   =  =hGG%*		*b1188==yyB//yyB//6**0b11ii)44"4	
 	
 		
 ; 9==44:;;AACCIIKK;&&%MM*55;BBDDKKCPPL2<@@ "!>#> )HNN,<,<< 
@[L,>,>,@,@@ 	  %	 E6  immH55;<<BBDD #GR006688E   DIMM)44:;;AACC 1266<<>> @2B77==??   E   HGGGGG++--E V  
 $, "4
 
 	
 9	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 ),ii 	#6#6#8#8 	@
 *    #}}((B77""8,,299;;W?U?U?W?W..00K4K{B//77)** 	9sww7J/K/K 	9'*+A'B$'(;$<    ww/00 Y;>?W;X !78www 9,/L ) \KY]]9-E-EKLLRRTT 0JB!O!O!U!U!W!WXX%%n55 	>O 	 &0MvMMM$% %)&8	 	GG &.MvMMM$% &8 G  	;*:G&'  #H--G D
7$	114X>> !9!5!566 			'":;;I+4<'9''''"DOXOOOO!&    9==44:;;AACCIIKK8##%MM*55;BBDDKKCPPLH599Z#<#<#C#CC#H#H%y  0EIIiQS<T<TUUHH(HH"%immJ&?&?&E2"F"F"L"L"N"N"T"T"V"V-immJ.G.GHHO::: FEEEEE)IY]]9b-I-I
228ZHH  (%I(Tg%h%h (*
 4H== ('H666EEEEEE228XxPPHz!!DXNNH   yyB//ii%00"4
 
 	
 *-)+  G
 %7G !Nsv   M M+*M+Q 
R%RR*BX +X/.X/9A9Z3 3+[! [!+B]- -+^^%A9` +aaerrorrL   c                h    t          | t                    rt          |           S t          |           S rk   )r   r   r   r(   )r  s    r.   format_runtime_provider_errorr  .  s.    %## ( '''u::r0   )r&   )r'   r(   r)   r(   r*   r(   )r1   r(   r*   r(   )r:   r(   r*   r;   )rE   r(   rF   r(   r*   r;   )rQ   r(   r*   rR   )r]   r^   rQ   r(   r*   r(   )rQ   r(   r*   r(   )rQ   r(   r*   r;   )r*   r^   rk   )r   rR   r   rR   r*   r;   )r]   r^   r   r(   r*   r(   )r   r   r*   rR   )r*   r(   )r   r(   r`   r(   r]   r   r*   r(   )r   r(   r   r
   r   r(   r]   r   r   r   r   rR   r*   r^   )r   rR   r*   r(   )NN)
rQ   r(   r   r(   r   rR   r   rR   r*   r   )r   r^   r  r^   r*   r  )r   r(   r*   r   )r   r(   r*   r;   )rQ   rR   r*  rR   r*   rR   )r2  r^   r*   r^   )r   r(   r6  rR   r7  rR   r*   r   )r   r(   r6  rR   r7  rR   r*   r^   )r   r(   r]   r^   r6  rR   r7  rR   r   rR   r*   r^   )r   r(   r   r(   r]   r^   r6  rR   r7  rR   r*   r   )
r   rR   r6  rR   r7  rR   r   rR   r*   r^   )r  rL   r*   r(   )W__doc__
__future__r   loggingr,  r   urllib.parser   typingr   r   r   	getLogger__name__rd   
hermes_clir   r   agent.credential_poolr	   r
   r   r   r   agent.secret_scoper   r,   rK   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   rn  r   r    r!   hermes_constantsr"   utilsr#   r$   r%   r/   r9   rD   rP   r\   rh   r   r   r   r   r   r   r   rb   r   r   r   r   r  r
  r  r"  r$  r)  r0  r&  r4  rM  r_  ry  r  r  r  rt   r0   r.   <module>r     sy   M M " " " " " "  				 				 ! ! ! ! ! ! & & & & & & & & & &		8	$	$ ' ' ' ' ' '              9 8 8 8 8 8                                   $         
 1 0 0 0 0 0 C C C C C C C C C C
/ 
/ 
/ 
/ 
/3 3 3 3= = = =
5 5 5 5<& & & &RB B B B,61 61 61 61r" " " "J   .   ,8 8 8 8 8"" " " "$      0 0 0 0   > +/%)"&L L L L L L^    , (,#'	    @   0 0 0 0] ] ] ]@   0 0 0 0j #%)< < < < < <~8 8 8 8, , , , '+'+	A A A A A AN '+'+	K K K K K Kd '+'+"&f f f f f f\ '+'+X X X X X Xz  $&*'+"&@	 @	 @	 @	 @	 @	F     r0   