
    Ӄiv                       d Z ddlmZ ddlZddlZddl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 ddl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! dd	l"m#Z# d8dZ$d9dZ%d:dZ&d;dZ'd<d=dZ(d>dZ)h dZ*d?dZ+dddd@d&Z,d<dAd(Z-	 d<dBd+Z.dCd,Z/ddd-dDd0Z0ddd-dEd1Z1ddd-dFd2Z2dddd3dGd4Z3dHd7Z4dS )IzGShared runtime provider resolution for CLI, gateway, cron, and helpers.    )annotationsN)AnyDictOptional)auth)CredentialPoolPooledCredentialget_custom_provider_pool_key	load_pool)
	AuthErrorDEFAULT_CODEX_BASE_URLPROVIDER_REGISTRYformat_auth_errorresolve_provider resolve_nous_runtime_credentials!resolve_codex_runtime_credentials$resolve_api_key_provider_credentials-resolve_external_process_provider_credentialshas_usable_secret)load_config)OPENROUTER_BASE_URLvaluestrreturnc                v    |                                                                                      dd          S )N -)striplowerreplace)r   s    8/home/ubuntu/hermes-agent/hermes_cli/runtime_provider.py_normalize_custom_provider_namer"      s,    ;;==  ((c222    base_urlOptional[str]c                    | pd                                                                                     d          }d|v rd|vrdS dS )zAuto-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).
     /zapi.openai.com
openroutercodex_responsesN)r   r   rstrip)r$   
normalizeds     r!   _detect_api_mode_for_urlr-   "   sS     .b''))//1188==J:%%,j*H*H  4r#   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 n# t          $ r Y nw xY wdS )zFQuery a local server for its model name when only one model is loaded.r'   r   Nr(   z/v1z/models   )timeoutdata   id)requestsr+   endswithgetokjsonlen	Exception)r$   r4   urlrespmodelsmodel_ids         r!   _auto_detect_local_modelr?   .   s     rooc""||E"" 	5LC||C)OQ|777 	$YY[[__VR00F6{{a!!9==r22 $#O   2s   B.B6 6
CCDict[str, Any]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modeldefaultr'   r$   	localhostz	127.0.0.1)r   r6   
isinstancedictr   r?   r   )config	model_cfgcfgrC   r$   is_localis_fallbackdetecteds           r!   _get_model_configrM   C   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??,,--Ir#   providerconfigured_providerboolc                    | 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'   Tcustomcustom:)r   r   
startswith)rN   rO   normalized_providernormalized_configureds       r!   $_provider_supports_explicit_api_moderW   Y   s     $>r002288::06B==??EEGG  th&&$0_4I4T4TU^4_4__ $777r#   rH   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)
NrN   r'   api_modecopilotrC   chat_completionsr   )copilot_model_api_mode)rX   )	r   r6   r   r   _parse_api_moderW   hermes_cli.modelsr]   r:   )rH   rX   rO   configured_mode
model_namer]   s         r!   _copilot_runtime_api_moderb   j   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>   r*   r\   anthropic_messagesrawr   c                    t          | t                    r1|                                                                 }|t          v r|S dS )z@Validate an api_mode value from config. Returns None if invalid.N)rE   r   r   r   _VALID_API_MODES)rd   r,   s     r!   r^   r^      sD    #s YY[[&&((
)))4r#   )rH   poolentryr	   requested_providerOptional[Dict[str, Any]]rg   Optional[CredentialPool]c           	        |pt                      }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    rd}t	          |                    d          pd                                                                          }d}	|d
k    rIt	          |                    d          pd                                                              d          }	|	p|pd}n| dk    r|pt          }n| dk    rd}n| dk    r t          |t          |dd                    }nt	          |                    d          pd                                                                          }
t          |                    d                    }|rt          | |
          r|}nU| dv r'ddlm}  || |                    dd                    }n*|                    d                              d          rd}|dk    r| dv rt          j        dd|          }| |||t          |dd          ||dS )Nruntime_base_urlr$   r'   r(   runtime_api_keyaccess_tokenr\   openai-codexr*   	anthropicrc   rN   https://api.anthropic.comr)   nousr[   rZ   zopencode-zenzopencode-gor   opencode_model_api_moderC   
/anthropic/v1/?$sourcerg   )rN   rZ   r$   rX   ry   credential_poolri   )rM   getattrr+   r   r   r6   r   r   r   rb   r^   rW   r_   rv   r5   resub)rN   rh   ri   rH   rg   r$   rX   rZ   cfg_providercfg_base_urlrO   r`   rv   s                r!    _resolve_runtime_from_pool_entryr      s    0.00I1488bGE:W[<\<\b`bjjknooHe.55[XZ9[9[G!H>!!$55	[	 	 '9==44:;;AACCIIKK;&&y}}Z88>B??EEGGNNsSSLJ8J/J	\	!	!22	V		%	Y		,YGXZ\8]8]^^!)--
";";"ArBBHHJJPPRR))--
*C*CDD 	,CHNabb 	,&HH888AAAAAA..xyRT9U9UVVHH__S!!**<88 	,+H '''H8W,W,W6)R22 %6220  r#   	requestedc                   | r:|                                  r&|                                                                  S t                      }|                    d          }t	          |t
                    r:|                                 r&|                                                                 S t          j        dd                                                                           }|r|S dS )z=Resolve provider request from explicit arg, config, then env.rN   HERMES_INFERENCE_PROVIDERr'   auto)r   r   rM   r6   rE   r   osgetenv)r   rH   r~   env_providers       r!   resolve_requested_providerr      s     )Y__&& )  &&(((!##I==,,L,$$ ,););)=)= ,!!##))+++ 98"==CCEEKKMML 6r#   provider_labelapi_mode_overridec                L   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.Nrn   ro   r'   r\   zpool:)rN   rZ   r$   rX   ry   rz   )r
   r   has_credentialsselectr{   r-   r:   )r$   r   r   pool_keyrg   rh   pool_api_keys          r!   _try_resolve_from_custom_poolr      s     ,H55H t""##%% 	4=4u&7>>d'%Q_acBdBd 	4&)e-Eh-O-OeSe #(h((#
 
 	
    tts"   #B B $B 8B 
B#"B#c           	        t          | pd          }|r|dk    rd S |dk    rd S |                    d          s'	 t          j        |           d S # t          $ r Y nw xY wt                      }|                    d          }t          |t                    s1t          |t                    rt                              d           d S |D ]}t          |t                    s|                    d          }|                    d          }t          |t                    rt          |t                    snt          |          }d| }|||hvr|                                |                                t          |                    d	d          pd                                          d
}	t          |                    d                    }
|
r|
|	d<   |	c S d S )Nr'   rR   r   rS   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.namer$   rX   )r   r$   rX   rZ   )r"   rT   auth_modr   r   r   r6   rE   listrF   loggerwarningr   r   r^   )ri   requested_normrG   r   rh   r   r$   	name_normmenu_keyresultrZ   s              r!   _get_named_custom_providerr      s   45G5M2NNN ^x77t
 t$$Y// 	%n555 4  	 	 	D	
 ]]Fzz"455&-- &-- 	NN3  
 t!  %&& 	yy  99Z(($$$ 	Jx,E,E 	3D99	(Y(()X!666JJLL ((599Y339r::@@BB
 

 #599Z#8#899 	*!)F:4s   A 
AAexplicit_api_keyexplicit_base_urlr   r   c           	        t          |           }|sd S |pd                                p|                    dd                              d          }|sd S t	          |d|                    d                    }|r|S |pd                                t          |                    dd          pd                                          t          j        dd                                          t          j        dd                                          g}t          d	 |D             d          }d|                    d          pt          |          pd
||pdd|                    d|            dS )Nr'   r$   r(   rR   rZ   rX   OPENAI_API_KEYOPENROUTER_API_KEYc              3  8   K   | ]}t          |          |V  d S N)r   .0	candidates     r!   	<genexpr>z0_resolve_named_custom_runtime.<locals>.<genexpr>D  s1      bb)EVW`EaEabIbbbbbbr#   r\   no-key-requiredzcustom_provider:r   rN   rZ   r$   rX   ry   )
r   r   r6   r+   r   r   r   r   nextr-   )ri   r   r   custom_providerr$   pool_resultapi_key_candidatesrX   s           r!   _resolve_named_custom_runtimer   (  s    11CDDO t 
	 b'')) 	/z2..fSkk   t 0(ODWDWXbDcDcddK  
	R&&((O	2..4"55;;==
	"B''--//
	&++1133	 bb/AbbbdfggG #''
33 #H--//V_%8%8AS%T%TVV  r#   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                                                                }	|                                                                }t          j        dd                                          }
d}|                                r!|s|	dk    r|r|dk    rd}n|	d	k    r|d	k    rd}|pd                                p |r|                                ndp|
pt          	                    d
          }d|v }|r*|t          j        d          t          j        d          g}n[d|                                v }||r|nd|rt          j        d          ndt          j        d          t          j        d          g}t          d |D             d          }|s|rdnd}|	d	k    rd	nd}|d	k    r7|r5t          ||t          |                    d                              }|r|S |d	k    r|s|sd}|t          |                    d                    pt          |          pd|||dS )Nr$   r'   rN   )rX   apir   Fr   TrR   r(   zopenrouter.air   r   z
ollama.comOLLAMA_API_KEYc              3  z   K   | ]6}t          |          t          |pd                                           V  7dS )r'   N)r   r   r   r   s     r!   r   z._resolve_openrouter_runtime.<locals>.<genexpr>  sI      jj)M^_hMiMijY_"			#	#	%	%jjjjjjr#   explicitz
env/configr)   rZ   r   r\   r   )rM   rE   r6   r   r   r   r   r   r   r+   r   r   r^   r-   )ri   r   r   rH   r   r~   cfg_api_keykvr   env_openrouter_base_urluse_config_base_urlr$   _is_openrouter_urlr   _is_ollama_urlrX   ry   effective_providerr   s                       r!   _resolve_openrouter_runtimer   Q  s    "##I0:9==;T;TVY0Z0Zb9==,,,`bL0:9==;T;TVY0Z0Zb9==,,,`bLK  MM!a 	!'')) 	''))KE(.B5577==??N%%''--//L i(=rBBHHJJ
   '$5 'V## +<6#9#9&*#x''LH,D,D"& 
	 b'')) 	$7?L   R	"	 fSkk  )H4 
I*++I&''
 &)9)99/7[[R,:BRY'(((I&''I*++
 jj7Ijjj
 G
 -T0ATZZF &4x%?%?\ X%%(%3(/)--
:S:S*T*T
 
  	X%%g%>P%# '#IMM*$=$=>> #H--  r#   c                	   t          |pd                                          }t          |pd                                                              d          }|s|sd S | dk    rt          |                    d          pd                                                                          }d}|dk    rIt          |                    d          pd                                                              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 }|pRt          |                    d          pt          j                                                                      d          }|p5t          |                    d          pd                                          }|                    d          p|                    d          }|st          t          dt          t!          j        dd                              t%          t!          j        dd                              }|                    dd          }|                    d          }|s+|                    dd                              d          p|}dd||d||dS t'          j        |           }|rz|j        dk    rnd}|j        r?t!          j        |j        d                                                              d          }|}|sH| dk    r9t-          |           }|                    dd                              d          }n	|p|j        }|}|sPt-          |           }|                    dd          }|s)|                    dd                              d          }d}| d k    rt1          ||          }nQt3          |                    d!                    }|r|}n*|                    d                              d"          rd
}| ||                    d          |d|dS d S )#Nr'   r(   rq   rN   r$   rr   r   resolve_anthropic_tokenNo Anthropic credentials found. Set ANTHROPIC_TOKEN or ANTHROPIC_API_KEY, run 'claude setup-token', or authenticate with 'claude /login'.rc   r   rN   rZ   r$   rX   ry   ri   rp   rX   last_refreshr*   rN   rZ   r$   rX   ry   r   ri   rs   inference_base_url	agent_keyagent_key_expires_at
expires_at<   HERMES_NOUS_MIN_KEY_TTL_SECONDS1800HERMES_NOUS_TIMEOUT_SECONDS15min_key_ttl_secondstimeout_secondsr\   rN   rZ   r$   rX   ry   r   ri   zkimi-codingr[   rZ   rw   )r   r   r+   r6   r   agent.anthropic_adapterr   r   r   r   r   get_provider_auth_stateDEFAULT_NOUS_INFERENCE_URLr   maxintr   r   floatr   	auth_typebase_url_env_varr   r   rb   r^   r5   )rN   ri   rH   r   r   r~   r   r$   rX   r   r   credsstater   pconfigenv_urlrZ   r`   s                     r!   _resolve_explicit_runtimer     sg    +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$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599122Yh6YZZ``bbiijmnn 	 #Oc%))K*@*@*FB&G&G&M&M&O&OYY566Q%))L:Q:Q
 	M4$'C	:[]c0d0d,e,e$f$f %bi0Mt&T&T U U  E ii	2..G<00J$ M 99Z44;;C@@LH*  $"4
 
 	
  #H--G %
7$	11# 	Ri 8"==CCEELLSQQG$ 	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-immJ.G.GHHO 0*%%..|<< 0/ !  ,, "4
 
 	
 4r#   )r   r   r   c                   t          |           }t          |||          }|r||d<   |S t          |||          }t                      }t	          |||||          }|r|S |dk    }|dk    rt          |                    d          pd                                                                          }	t          |                    d          pd                                          }
t          j
        d	d                                          }t          j
        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|rf|                                rR|                                }d}|"t!          |dd          pt!          |dd          }||rt#          |||||          S |dk    r	 t%          t'          dt)          t          j
        dd                              t+          t          j
        dd                              }dd|                    dd                              d          |                    dd          |                    dd          |                    d          |dS # t.          $ r$ |d k    r t0                              d!           Y nw xY w|d"k    r	 t5                      }d"d#|                    dd                              d          |                    dd          |                    dd$          |                    d%          |d&S # t.          $ r$ |d k    r t0                              d'           Y nw xY w|d(k    rt7          |          }d(d|                    dd                              d          |                    dd          |                    d)d          t9          |                    d*          pg           |                    dd+          |d,S |d-k    rd.d/lm}  |            }|st/          d0          t          |                    d          pd                                                                          }	d}
|	d-k    r<|                    d          pd                                                    d          }
|
pd1}d-d2||d3|d4S t?          j        |          }|r|j         dk    rtC          |          }|                    dd                              d          }d}|d5k    r%tE          ||                    dd                    }nt          |                    d          pd                                                                          }tG          |                    d6                    }|rtI          ||          r|}nU|d7v r'd.d8l%m&}  |||                    d9d                    }n*|                    d          '                    d:          rd2}|d2k    r|d7v rtQ          j)        d;d|          }||||                    dd          |                    dd3          |d4S tU          |||          }||d<   |S )<z9Resolve runtime provider credentials for agent execution.)ri   r   r   ri   r   )rN   ri   rH   r   r   r)   rN   r'   r$   OPENAI_BASE_URLr   >   r   rR   T>   r   r)   Nrn   ro   )rN   rh   ri   rH   rg   rs   r   r   r   r   r   r   r\   r(   rX   ry   portalr   r   r   zUAuto-detected Nous provider but credentials failed; falling through to next provider.rp   r*   zhermes-auth-storer   r   zVAuto-detected Codex provider but credentials failed; falling through to next provider.zcopilot-acpcommandargsprocess)rN   rZ   r$   rX   r   r   ry   ri   rq   r   r   r   rr   rc   envr   r[   rZ   rt   ru   rC   rw   rx   )+r   r   r   rM   r   r   r6   r   r   r   r   rP   r   r:   r   r   r{   r   r   r   r   r   r+   r   r   infor   r   r   r   r   r   r   r   rb   r^   rW   r_   rv   r5   r|   r}   r   )r   r   r   ri   custom_runtimerN   rH   explicit_runtimeshould_use_poolr~   r   env_openai_base_urlr   has_custom_endpointhas_runtime_overriderg   rh   r   r   r   tokenr$   r   rZ   rO   r`   rv   runtimes                               r!   resolve_runtime_providerr   6  s"    4I>>2-)+  N
  /A+,)+  H
 "##I0-)+     ,.O<9==44:;;AACCIIKK9==44:;;AACC i(92>>DDFF"$),A2"F"F"L"L"N"N" '"'&
 

  	'L,>>>"&#$4$I8IJJ"88 )'')(( 	&5?y"""4    $$&& 0$77 65."55  3!#5#    6	=4$'C	:[]c0d0d,e,e$f$f %bi0Mt&T&T U U  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 < = = = = =	= =  =hGG%*		*b1188==yyB//yyB//6**0b11ii)44"4	
 	
 		
 ;CCCCCC'')) 	R   9==44:;;AACCIIKK;&&%MM*55;BBDDKKCPPL>#>#, "4
 
 	
  #H--G 
7$	114X>>99Z,,33C88%y  0EIIiQS<T<TUUHH"%immJ&?&?&E2"F"F"L"L"N"N"T"T"V"V-immJ.G.GHHO 0#GRe#f#f 0*<<<EEEEEE228Y]]9VX=Y=YZZ %%..|<< 0/+++<[0[0[viX66H   yyB//ii%00"4
 
 	
 *-)+  G
 %7G !Ns8   3F FFC
K +L LA9N +N32N3errorr:   c                h    t          | t                    rt          |           S t          |           S r   )rE   r   r   r   )r   s    r!   format_runtime_provider_errorr     s.    %## ( '''u::r#   )r   r   r   r   )r$   r   r   r%   )r$   r   r   r   )r   r@   r   )rN   r%   rO   r%   r   rP   )rH   r@   rX   r   r   r   )rd   r   r   r%   )rN   r   rh   r	   ri   r   rH   rj   rg   rk   r   r@   )r   r%   r   r   )r$   r   r   r   r   r%   r   rj   )ri   r   r   rj   )ri   r   r   r%   r   r%   r   rj   )ri   r   r   r%   r   r%   r   r@   )rN   r   ri   r   rH   r@   r   r%   r   r%   r   rj   )r   r%   r   r%   r   r%   r   r@   )r   r:   r   r   )5__doc__
__future__r   loggingr   r|   typingr   r   r   	getLogger__name__r   
hermes_clir   r   agent.credential_poolr   r	   r
   r   hermes_cli.authr   r   r   r   r   r   r   r   r   r   hermes_cli.configr   hermes_constantsr   r"   r-   r?   rM   rW   rb   rf   r^   r   r   r   r   r   r   r   r   r    r#   r!   <module>r      s   M M " " " " " "  				 				 & & & & & & & & & &		8	$	$ ' ' ' ' ' ' k k k k k k k k k k k k                        * ) ) ) ) ) 0 0 0 0 0 03 3 3 3	 	 	 	   *   ,8 8 8 8 8"" " " "$ QPP     +/%)6 6 6 6 6 6r    , (,    >2 2 2 2p '+'+	& & & & & &X '+'+	^ ^ ^ ^ ^ ^L '+'+A A A A A AL  $&*'+	D D D D D DN     r#   