
    Ji|                       d Z ddlmZ ddlZddlZddlZddlZddlZddlZddl	m
Z
mZmZ ddlmZmZmZmZmZmZ ddl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$  ej%        e&          Z'dDd
Z(dZ)dZ*dZ+dZ,dZ-dZ.dZ/dZ0dZ1e.e/e0e1hZ2dZ3dZ4dZ5 e6h d          Z7e
 G d d                      Z8dEdZ9dFd!Z:dGd$Z;dHd'Z<dId)Z=dJdKd+Z>dLd.Z?dMd0Z@dNd3ZAdOd5ZB G d6 d7          ZCdPd:ZDdQd;ZEdRd=ZFdRd>ZGdSdAZHdTdBZIdUdCZJdS )Vz<Persistent multi-credential pool for same-provider failover.    )annotationsN)	dataclassfieldsreplace)AnyDictListOptionalSetTuple)OPENROUTER_BASE_URL)!ACCESS_TOKEN_REFRESH_SKEW_SECONDS'CODEX_ACCESS_TOKEN_REFRESH_SKEW_SECONDS!DEFAULT_AGENT_KEY_MIN_TTL_SECONDSPROVIDER_REGISTRY_agent_key_is_usable_codex_access_token_is_expiring_decode_jwt_claims_is_expiring_load_auth_store_load_provider_stateread_credential_poolwrite_credential_poolreturnOptional[dict]c                 F    	 ddl m}   |             S # t          $ r Y dS w xY w)z.Load config.yaml, returning None on any error.r   load_configN)hermes_cli.configr   	Exceptionr   s    2/home/ubuntu/hermes-agent/agent/credential_pool.py_load_config_safer"   "   sG    111111{}}   tts    
  ok	exhaustedoauthapi_keymanual
fill_firstround_robinrandom
least_usedi  iQ zcustom:>   tlsscope	client_id
expires_in
token_typeobtained_atagent_key_idportal_base_urlagent_key_reusedagent_key_expires_inagent_key_obtained_atc                  j   e Zd ZU ded<   ded<   ded<   ded<   ded<   ded<   ded	<   d
Zded<   d
Zded<   d
Zded<   d
Zded<   d
Zded<   d
Z	ded<   d
Z
ded<   d
Zded<   d
Zded<   d
Zded<   d
Zded<   dZded<   d
Zded<   d Zd'dZed(d#            Zd)d$Zed*d%            Zed+d&            Zd
S ),PooledCredentialstrprovideridlabel	auth_typeintprioritysourceaccess_tokenNOptional[str]refresh_tokenlast_statuszOptional[float]last_status_atOptional[int]last_error_codebase_url
expires_atexpires_at_mslast_refreshinference_base_url	agent_keyagent_key_expires_atr   request_countDict[str, Any]extrac                &    | j         	i | _         d S d S N)rQ   selfs    r!   __post_init__zPooledCredential.__post_init__l   s    :DJJJ     namec                    |t           v r| j                            |          S t          dt	          |           j         d|          )N'z' object has no attribute )_EXTRA_KEYSrQ   getAttributeErrortype__name__)rU   rX   s     r!   __getattr__zPooledCredential.__getattr__p   sJ    ;:>>$'''Xd!4XXPTXXYYYrW   payloadr   'PooledCredential'c                   d t          |           D             }fd|D             }fdt          D             }||d<   |                    dt          j                    j        d d                    |                    d                    d|                     |                    d	t                     |                    d
d           |                    dt                     |                    dd            | dd|i|S )Nc                2    h | ]}|j         d k    |j         S )r:   rX   .0fs     r!   	<setcomp>z-PooledCredential.from_dict.<locals>.<setcomp>w   s&    KKK!af
6J6Jqv6J6J6JrW   c                D    i | ]}|v |                     |          S  )r\   rg   kra   s     r!   
<dictcomp>z.PooledCredential.from_dict.<locals>.<dictcomp>x   s*    GGGa!w,,7;;q>>,,,rW   c                :    i | ]}|v |         ||         S rS   rk   rl   s     r!   rn   z.PooledCredential.from_dict.<locals>.<dictcomp>y   s1    ___1qG||PQ
H^GAJH^H^H^rW   rQ   r;      r<   r@   r=   r?   r   rA    r:   rk   )	r   r[   
setdefaultuuiduuid4hexr\   AUTH_TYPE_API_KEYSOURCE_MANUAL)clsr:   ra   field_namesdatarQ   s     `   r!   	from_dictzPooledCredential.from_dictu   s   KKvc{{KKKGGGG;GGG_______Wdjll.rr2333Xx!@!@AAA%6777
A&&&-000+++s--H----rW   c                    h d}i }t          |           D ]6}|j        dv rt          | |j                  }|	|j        |v r
|||j        <   7| j                                        D ]\  }}||||<   |S )N>   rD   rE   rG   )r:   rQ   )r   rX   getattrrQ   items)rU   _ALWAYS_EMITresult	field_defvaluerm   vs          r!   to_dictzPooledCredential.to_dict   s    KKK!# 	/ 	/I~!666D).11E INl$B$B).y~&J$$&& 	 	DAq}q	rW   c                ~    | j         dk    rt          | j        p| j        pd          S t          | j        pd          S )Nnousrq   )r:   r9   rM   rA   rT   s    r!   runtime_api_keyz PooledCredential.runtime_api_key   sB    =F""t~@):@bAAA4$*+++rW   c                B    | j         dk    r| j        p| j        S | j        S )Nr   )r:   rL   rH   rT   s    r!   runtime_base_urlz!PooledCredential.runtime_base_url   s'    =F""*;dm;}rW   )rX   r9   )r:   r9   ra   rP   r   rb   )r   rP   )r   r9   )r   rB   )r_   
__module____qualname____annotations__rC   rD   rE   rG   rH   rI   rJ   rK   rL   rM   rN   rO   rQ   rV   r`   classmethodr{   r   propertyr   r   rk   rW   r!   r8   r8   U   s        MMMGGGJJJNNNMMMKKK#'M''''!%K%%%%&*N****%)O))))"H"""" $J$$$$#'M''''"&L&&&&(,,,,,#I####*.....M E      Z Z Z Z
 . . . [.    , , , X,
    X  rW   r8   tokenr9   fallbackc                    t          |           }dD ]V}|                    |          }t          |t                    r*|                                r|                                c S W|S )N)emailpreferred_usernameupn)r   r\   
isinstancer9   strip)r   r   claimskeyr   s        r!   label_from_tokenr      sh    &&F5 ! !

3eS!! 	!ekkmm 	!;;==   OrW   entriesList[PooledCredential]r>   c                >    t          d | D             d          dz   S )Nc              3  $   K   | ]}|j         V  d S rS   r?   rg   entrys     r!   	<genexpr>z!_next_priority.<locals>.<genexpr>   s$      445444444rW   )default   )max)r   s    r!   _next_priorityr      s)    44G444bAAAAEErW   r@   boolc                    | pd                                                                 }|t          k    p|                    t           d          S )Nrq   :)r   lowerrw   
startswith)r@   
normalizeds     r!   _is_manual_sourcer      sJ    ,B%%''--//J&T**?*?=@S@S@S*T*TTrW   
error_coderF   c                *    | dk    rt           S t          S )zHReturn cooldown seconds based on the HTTP status that caused exhaustion.i  )EXHAUSTED_TTL_429_SECONDSEXHAUSTED_TTL_DEFAULT_SECONDS)r   s    r!   _exhausted_ttlr      s    S((((rW   rX   c                v    |                                                                                      dd          S )z>Normalize a custom provider name for use as a pool key suffix. -)r   r   r   re   s    r!   _normalize_custom_pool_namer      s,    ::<<''S111rW   configc              #  <  K   | t                      } | dS |                     d          }t          |t                    sdS |D ]V}t          |t                    s|                    d          }t          |t
                    sCt          |          |fV  WdS )zJYield (normalized_name, entry_dict) for each valid custom_providers entry.Ncustom_providersrX   )r"   r\   r   listdictr9   r   )r   r   r   rX   s       r!   _iter_custom_providersr      s      ~"$$~zz"455&-- ! 7 7%&& 	yy  $$$ 	)$//666667 7rW   rH   rB   c                @   | sdS |                                                      d          }t                      D ]c\  }}t          |                    d          pd                                                               d          }|r||k    rt
           | c S ddS )zLook up the custom_providers list in config.yaml and return 'custom:<name>' for a matching base_url.

    Returns None if no match is found.
    N/rH   rq   )r   rstripr   r9   r\   CUSTOM_POOL_PREFIX)rH   normalized_url	norm_namer   	entry_urls        r!   get_custom_provider_pool_keyr      s    
  t^^%%,,S11N244 6 6	5		*--344::<<CCCHH	 	6n44(5)555554rW   	List[str]c                 X     t          d           t           fd D                       S )z?Return all 'custom:*' pool keys that have entries in auth.json.Nc              3     K   | ]P}|                     t                    t                              |          t                    D|         L|V  Qd S rS   )r   r   r   r\   r   )rg   r   	pool_datas     r!   r   z-list_custom_pool_providers.<locals>.<genexpr>   sx        >>,-- y}}S))400 cN	     rW   )r   sorted)r   s   @r!   list_custom_pool_providersr      sH    $T**I          rW   pool_keyOptional[Dict[str, Any]]c                    |                      t                    sdS | t          t                    d         }t                      D ]\  }}||k    r|c S dS )zWReturn the custom_providers config entry matching a pool key like 'custom:together.ai'.N)r   r   lenr   )r   suffixr   r   s       r!   _get_custom_provider_configr      so    122 tc,--../F244  	5LLL 4rW   r:   c                H   t                      }|t          S |                    d          }t          |t                    st          S t          |                    | d          pd                                                                          }|t          v r|S t          S )z8Return the configured selection strategy for a provider.Ncredential_pool_strategiesrq   )	r"   STRATEGY_FILL_FIRSTr\   r   r   r9   r   r   SUPPORTED_POOL_STRATEGIES)r:   r   
strategiesstrategys       r!   get_pool_strategyr      s      F~""899Jj$'' #"":>>(B//5266<<>>DDFFH,,,rW   c                      e Zd Zd.dZd/dZd/d	Zd0d
Zd1dZd2dZd3dZ	d4dZ
d5dZd6dZd7d8dZd1dZddd d9d#Zd1d$Zd1d%Zd:d&Zd1d'Zd1d(Zd;d*Zd<d,Zd=d-ZdS )>CredentialPoolr:   r9   r   r   c                    || _         t          |d           | _        d | _        t	          |          | _        t          j                    | _        d S )Nc                    | j         S rS   r   r   s    r!   <lambda>z)CredentialPool.__init__.<locals>.<lambda>  s    %. rW   r   )	r:   r   _entries_current_idr   	_strategy	threadingLock_lock)rU   r:   r   s      r!   __init__zCredentialPool.__init__  sK     w,H,HIII*.*844^%%


rW   r   r   c                *    t          | j                  S rS   )r   r   rT   s    r!   has_credentialszCredentialPool.has_credentials      DM"""rW   c                D    t          |                                           S )zCTrue if at least one entry is not currently in exhaustion cooldown.)r   _available_entriesrT   s    r!   has_availablezCredentialPool.has_available  s    D++--...rW   c                *    t          | j                  S rS   )r   r   rT   s    r!   r   zCredentialPool.entries  r   rW   Optional[PooledCredential]c                X      j         sd S t           fd j        D             d           S )Nc              3  <   K   | ]}|j         j        k    |V  d S rS   )r;   r   )rg   r   rU   s     r!   r   z)CredentialPool.current.<locals>.<genexpr>  s2      VVuTEU9U9UU9U9U9U9UVVrW   )r   nextr   rT   s   `r!   currentzCredentialPool.current  s;     	4VVVVVVVX\]]]rW   oldr8   newNonec                t    t          | j                  D ]"\  }}|j        |j        k    r|| j        |<    dS #dS )z4Swap an entry in-place by id, preserving sort order.N)	enumerater   r;   )rU   r   r   idxr   s        r!   _replace_entryzCredentialPool._replace_entry  sP    #DM22 	 	JCx36!!%(c" "	 	rW   c                N    t          | j        d | j        D                        d S )Nc                6    g | ]}|                                 S rk   r   r   s     r!   
<listcomp>z+CredentialPool._persist.<locals>.<listcomp>$  s     888U]]__888rW   )r   r:   r   rT   s    r!   _persistzCredentialPool._persist!  s6    M88$-888	
 	
 	
 	
 	
rW   r   status_coderF   c                    t          |t          t          j                    |          }|                     ||           |                                  |S )NrD   rE   rG   )r   STATUS_EXHAUSTEDtimer   r   )rU   r   r   updateds       r!   _mark_exhaustedzCredentialPool._mark_exhausted'  sR    (9;;'	
 
 
 	E7+++rW   forcec                  |j         t          k    s|j        s|r|                     |d            d S 	 | j        dk    rWddlm}  ||j        |j                            d                    }t          ||d         |d         |d         	          }nC| j        d
k    rRt          j        |j        |j                  }t          ||d         |d         |                    d                    }n| j        dk    r|j        |j        |j        |j        |j        |j        |j        |j        |j        |j        |j        |j        d}t          j        |t2          ||          }i }t5          |j                  }d t9          |          D             }	|                                D ]\  }
}|
|	v r|||
<   |
t<          v r|||
<   t          |fd|i|}n|S nU# t>          $ rH}t@          !                    d| j        |j"        |           |                     |d            Y d }~d S d }~ww xY wt          |tF          d d           }| $                    ||           | %                                 |S )N	anthropicr   )refresh_anthropic_oauth_purehermes_pkce)use_jsonrA   rC   rJ   )rA   rC   rJ   openai-codexrK   )rA   rC   rK   r   )rA   rC   r.   r3   rL   r0   r-   r1   rI   rM   rN   r,   )min_key_ttl_secondsforce_refresh
force_mintc                    h | ]	}|j         
S rk   re   rf   s     r!   ri   z0CredentialPool._refresh_entry.<locals>.<setcomp>i  s    >>>1>>>rW   rQ   z'Credential refresh failed for %s/%s: %sr   )&r=   AUTH_TYPE_OAUTHrC   r  r:   agent.anthropic_adapterr  r@   endswithr   auth_modrefresh_codex_oauth_purerA   r\   r.   r3   rL   r0   r-   r1   rI   rM   rN   r,   refresh_nous_oauth_from_stater   r   rQ   r   r~   r[   r    loggerdebugr;   	STATUS_OKr   r   )rU   r   r  r  	refreshedr  
nous_statefield_updatesextra_updates_field_namesrm   r   excs                r!   _refresh_entryzCredentialPool._refresh_entry2  s   ?o--U5H- 2$$UD1114=	}++PPPPPP88'"\22=AA  	 "!*>!:"+O"<"+O"<	   .00$=&' 	 "!*>!:"+O"<!*~!>!>	   &(($)$6%*%8!&','<*/*B"'"2"[#(#4"'"2!&,1,F 9 
 %B(I"'$	  	 !# $U[ 1 1>>u>>>%OO-- - -DAqL((+,a((k))+,a(!%NN}NNN 	 	 	LLBDMSXS[]`aaa  ---44444	
 'y_cdddE7+++s   F$G 
H+#=H&&H+c                .   |j         t          k    rdS | j        dk    rE|j        dS t	          |j                  t	          t          j                    dz            dz   k    S | j        dk    rt          |j        t                    S | j        dk    rdS dS )NFr  i  i r  r   )	r=   r  r:   rJ   r>   r  r   rA   r   rU   r   s     r!   _entry_needs_refreshz#CredentialPool._entry_needs_refresh|  s    ?o--5=K''"*uu*++s49;;3E/F/F/PPP=N**2"7   =F"" 5urW   Nentry_idrB   c                
   |p| j         }|sdS | j        5  t          | j                  D ]?\  }}|j        |k    r/t          ||j        dz             | j        |<    ddd           dS @	 ddd           dS # 1 swxY w Y   dS )zBIncrement request_count for tracking. Used by least_used strategy.Nr   rO   )r   r   r   r   r;   r   rO   )rU   r#  	target_idr   r   s        r!   	mark_usedzCredentialPool.mark_used  s   0 0	 	FZ 	 	'66  
U8y(()0eFY\]F])^)^)^DM#&		 	 	 	 	 	 	 	(	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	s   AA8)A88A<?A<c                l    | j         5  |                                 cd d d            S # 1 swxY w Y   d S rS   )r   _select_unlockedrT   s    r!   selectzCredentialPool.select  s}    Z 	+ 	+((**	+ 	+ 	+ 	+ 	+ 	+ 	+ 	+ 	+ 	+ 	+ 	+ 	+ 	+ 	+ 	+ 	+ 	+   )--Fclear_expiredrefreshr-  r.  c                  t          j                     }d}g }| j        D ]}|j        t          k    r^t	          |j                  }|j        r||j        z
  |k     r<|r2t          |t          dd          }| 	                    ||           |}d}|r1| 
                    |          r|                     |d          }	|	|	}|                    |           |r|                                  |S )a  Return entries not currently in exhaustion cooldown.

        When *clear_expired* is True, entries whose cooldown has elapsed are
        reset to STATUS_OK and persisted.  When *refresh* is True, entries
        that need a token refresh are refreshed (skipped on failure).
        FNr   Tr  )r  r   rD   r  r   rG   rE   r   r  r   r"  r  appendr   )
rU   r-  r.  nowcleared_any	availabler   ttlclearedr  s
             r!   r   z!CredentialPool._available_entries  s    ikk,.	] 	$ 	$E $444$U%:;;' C%2F,F,L,L  '%eSWimnnnG''w777#E"&K "444U;; " //U/CC	$!U#### 	MMOOOrW   c                   |                      dd          }|s	d | _        d S | j        t          k    r"t	          j        |          j        | _        S | j        t          k    r3t          |          dk    r t          |d           j        | _        S | j        t          k    rt          |          dk    r|d         fd| j        D             }|                    t          t          | j                  dz
                       d	 t          |          D             | _        |                                  j        | _        |                                 pS |d         j        | _        S )
NTr,  r   c                    | j         S rS   r%  )es    r!   r   z1CredentialPool._select_unlocked.<locals>.<lambda>  s     rW   r   r   c                4    g | ]}|j         j         k    |S rk   r;   )rg   	candidater   s     r!   r   z3CredentialPool._select_unlocked.<locals>.<listcomp>  s)    \\\Y9<SXS[C[C[yC[C[C[rW   r   c                6    g | ]\  }}t          ||           S r   r   )rg   r   r<  s      r!   r   z3CredentialPool._select_unlocked.<locals>.<listcomp>  s)    ggg.#yWY===gggrW   )r   r   r   STRATEGY_RANDOMr*   choicer;   STRATEGY_LEAST_USEDr   minSTRATEGY_ROUND_ROBINr   r1  r   r   r   r   )rU   r4  rotatedr   s      @r!   r)  zCredentialPool._select_unlocked  so   ++$+MM	 	#D4>_,,M),,E$xDL>000S^^a5G5G	'@'@AAAE$xDL>111c)nnq6H6HaLE\\\\$-\\\GNN753t}3E3E3IJJJKKKggT]^eTfTfgggDMMMOOO$xD<<>>*U*! 8rW   c                r    |                                  }||S |                                 }|r|d         nd S )Nr   )r   r   )rU   r   r4  s      r!   peekzCredentialPool.peek  s>    ,,..N++--	(2y||d2rW   c                  | j         5  |                                 p|                                 }|	 d d d            d S |                     ||           d | _        |                                 cd d d            S # 1 swxY w Y   d S rS   )r   r   r)  r  r   )rU   r   r   s      r!   mark_exhausted_and_rotatez(CredentialPool.mark_exhausted_and_rotate  s    Z 	+ 	+LLNN=d&;&;&=&=E}	+ 	+ 	+ 	+ 	+ 	+ 	+ 	+   444#D((**	+ 	+ 	+ 	+ 	+ 	+ 	+ 	+ 	+ 	+ 	+ 	+ 	+ 	+ 	+ 	+ 	+ 	+s   ,A>0A>>BBc                l    | j         5  |                                 cd d d            S # 1 swxY w Y   d S rS   )r   _try_refresh_current_unlockedrT   s    r!   try_refresh_currentz"CredentialPool.try_refresh_current  s}    Z 	8 	85577	8 	8 	8 	8 	8 	8 	8 	8 	8 	8 	8 	8 	8 	8 	8 	8 	8 	8r+  c                    |                                  }|d S |                     |d          }||j        | _        |S )NTr0  )r   r  r;   r   )rU   r   r  s      r!   rK  z,CredentialPool._try_refresh_current_unlocked  sG    =4''T'::	 (|DrW   r>   c           	        d}g }| j         D ]X}|j        s|j        s|j        r,|                    t          |d d d                      |dz  }C|                    |           Y|r|| _         |                                  |S )Nr   r   r   )r   rD   rE   rG   r1  r   r   )rU   countnew_entriesr   s       r!   reset_statuseszCredentialPool.reset_statuses  s    ] 	* 	*E  *E$8 *E<Q *""75dSWim#n#n#nooo
""5)))) 	'DMMMOOOrW   indexc                   |dk     s|t          | j                  k    rd S | j                            |dz
            }d t          | j                  D             | _        |                                  | j        |j        k    rd | _        |S )Nr   c                6    g | ]\  }}t          ||           S r>  r?  )rg   new_priorityr   s      r!   r   z/CredentialPool.remove_index.<locals>.<listcomp>  s9     
 
 
#e EL111
 
 
rW   )r   r   popr   r   r   r;   )rU   rR  removeds      r!   remove_indexzCredentialPool.remove_index  s    199DM 2 2224-##EAI..
 
'0'?'?
 
 
 	wz))#DrW   c                    t          |t          | j                            }| j                            |           |                                  |S )Nr   )r   r   r   r1  r   r!  s     r!   	add_entryzCredentialPool.add_entry  sF    t}(E(EFFFU###rW   )r:   r9   r   r   )r   r   )r   r   )r   r   )r   r8   r   r8   r   r   )r   r   )r   r8   r   rF   r   r8   )r   r8   r  r   r   r   )r   r8   r   r   rS   )r#  rB   r   r   )r-  r   r.  r   r   r   )r   rF   r   r   )r   r>   )rR  r>   r   r   )r   r8   r   r8   )r_   r   r   r   r   r   r   r   r   r   r  r  r"  r'  r*  r   r)  rG  rI  rL  rK  rQ  rX  rZ  rk   rW   r!   r   r     s       & & & &# # # #/ / / /# # # #^ ^ ^ ^
   
 
 
 
	 	 	 	H H H HT   &	 	 	 	 	+ + + + ;@QV      <   :3 3 3 3+ + + +8 8 8 8              rW   r   ra   rP   c                B   d }t          |           D ]\  }}|j        |k    r|} n||                    dt          j                    j        d d                    |                    dt          |                      |                    d|                    d          p|           |                     t          
                    ||                     dS | |         }i }i }	d t          |          D             }
|                                D ]d\  }}|dv s||dk    r|j        r||
v rt          ||          |k    r|||<   8|t          v r#|j                            |          |k    r||	|<   e|s|	r"|	ri |j        |	|d<   t#          |fi || |<   dS d	S )
Nr;   rp   r?   r<   Tc                    h | ]	}|j         
S rk   re   rf   s     r!   ri   z _upsert_entry.<locals>.<setcomp>)  s    555qAF555rW   >   r;   r?   rQ   F)r   r@   rr   rs   rt   ru   r   r\   r1  r8   r{   r   r~   r<   r}   r[   rQ   r   )r   r:   r@   ra   existing_idxr   r   existingr  r  r  r   r   s                r!   _upsert_entryr_    s   L((  
U<6!!LE " 4!1"1"!5666:~g'>'>???7GKK$8$8$BFCCC'11(GDDEEEt|$HMM55F8$4$4555Lmmoo 
+ 
+
U$$$'>>hn>,x%%..%*c"K~!!#&&%//%*c"   	I%H%H-%HM'" ' B BM B Bt5rW   c                `  	 | dk    rdS dddddd	t          d	 |D             d
           }t          d |D             	fd          }g ||}d t          |          D             }d}t          |          D ]1\  }}|j        |k    r!t          ||          |||j                 <   d}2|S )Nr  Fr   r            )zenv:ANTHROPIC_TOKENzenv:CLAUDE_CODE_OAUTH_TOKENr	  claude_codezenv:ANTHROPIC_API_KEYc              3  B   K   | ]}t          |j                  |V  d S rS   r   r@   r   s     r!   r   z-_normalize_pool_priorities.<locals>.<genexpr>I  s2      GG5'8'F'FGGGGGGGrW   c                    | j         S rS   r   r   s    r!   r   z,_normalize_pool_priorities.<locals>.<lambda>J  s    %. rW   r   c              3  B   K   | ]}t          |j                  |V  d S rS   rf  r   s     r!   r   z-_normalize_pool_priorities.<locals>.<genexpr>M  s2      KK5+<U\+J+JKKKKKKKrW   c                n                         | j        t                              | j        | j        fS rS   )r\   r@   r   r?   r<   )r   source_ranks    r!   r   z,_normalize_pool_priorities.<locals>.<lambda>N  s/    OOEL#k*:*:;;NK
 rW   c                $    i | ]\  }}|j         |S rk   r;  )rg   r   r   s      r!   rn   z._normalize_pool_priorities.<locals>.<dictcomp>V  s     DDD:33DDDrW   r   T)r   r   r?   r   r;   )
r:   r   manual_entriesseeded_entriesordered	id_to_idxchangedrU  r   rj  s
            @r!   _normalize_pool_prioritiesrq  =  s   ;u  !'(!" K GGGGGG((  N KKGKKK
 
 
 
  N 100GDD71C1CDDDIG(11  e>\))+25<+P+P+PGIeh'(GNrW   Tuple[bool, Set[str]]c                   d}t                      }t                      }| dk    rddlm}m} d |            fd |            ffD ]\  }}|r|                    d          r|                    |           |t          || ||t          |                    dd          |                    d	          |                    d
          t          |                    dd          |          d          z  }nv| dk    rpt          |d          }	|	r\|                    d           |t          || ddt          |	                    dd          |	                    d          |	                    d          |	                    d          |	                    d          |	                    d          |	                    d          |	                    d          |	                    d          |	                    d          t          |	                    d          t                    r|	                    d          nd t          |	                    dd          d          d          z  }n| dk    rt          |d          }	t          |	t                    r|	                    d          nd }
t          |
t                    r|
                    d          r|                    d           |t          || ddt          |
                    dd          |
                    d          d|	                    d          t          |
                    dd          d          d          z  }||fS )NFr  r   )read_claude_code_credentialsread_hermes_oauth_credentialsr	  rd  accessTokenrq   refreshToken	expiresAt)r@   r=   rA   rC   rJ   r<   r   device_coderA   rC   rI   r0   r-   r.   r3   rL   rM   rN   r,   )r@   r=   rA   rC   rI   r0   r-   r.   r3   rL   rM   rN   r,   r<   r  tokensz%https://chatgpt.com/backend-api/codexrK   )r@   r=   rA   rC   rH   rK   r<   )setr   r  rt  ru  r\   addr_  r  r   r   r   r   )r:   r   rp  active_sources
auth_storert  ru  source_namecredsstaterz  s              r!   _seed_from_singletonsr  _  s|   G"uuN!##J;gggggggg 99;;<88::;#
 	 	K  =11 "";///="-%4(-		-(D(D).>)B)B).;)?)?!1%))M22N2NP[!\!\ 	  	( 
V		$Z88 	}---}+!0$)IInb$A$A%*YY%?%?"'))L"9"9"'))L"9"9"YYw//!&;!7!7',yy1B'C'C*/))4H*I*I!&;!7!7,1II6L,M,M/9%))E:J:JD/Q/Q[599U+++W[-eii.K.K][[ 	  G, 
^	#	#$Z@@(25$(?(?I8$$$Tfd## 	

>(B(B 	}---}+!0$*JJ~r$B$B%+ZZ%@%@ G$)IIn$=$=-fjj.L.Lm\\ 	  G N""rW   c                T   d}t                      }| dk    rit          j        dd                                          }|r<d}|                    |           |t          || ||t          |t          dd          z  }||fS t          j	        |           }|r|j
        t          k    r||fS d}|j        r?t          j        |j        d                                                              d          }t          |j                  }| dk    rg d	}|D ]}	t          j        |	d                                          }|s,d
|	 }|                    |           | dk    r|                    d          st           nt          }
|p|j        }|t          || |||
|||	d          z  }||fS )NF
openrouterOPENROUTER_API_KEYrq   zenv:OPENROUTER_API_KEYr@   r=   rA   rH   r<   r   r  )ANTHROPIC_TOKENCLAUDE_CODE_OAUTH_TOKENANTHROPIC_API_KEYenv:z
sk-ant-api)r{  osgetenvr   r|  r_  rv   r   r   r\   r=   base_url_env_varr   r   api_key_env_varsr   r  rL   )r:   r   rp  r}  r   r@   pconfigenv_urlenv_varsenv_varr=   rH   s               r!   _seed_from_envr    s   G"uuN<	.3399;; 	-Fv&&&}$!2$) 31 	  G &&#H--G 'g'+<<<&&G N)G4b99??AAHHMMG,--H;
 
 
  
 
	'2&&,,.. 	!!!6"""'/;'>'>uGWGWXdGeGe'>OOk|	8g8= & %$  	
 
 	
 N""rW   r}  Set[str]c                v    fd| D             }t          |          t          |           k    rdS || d d <   dS )Nc                    g | ]D}t          |j                  s,|j        v s#|j                            d           s|j        dv B|ES )r  >   rd  r	  )r   r@   r   )rg   r   r}  s     r!   r   z/_prune_stale_seeded_entries.<locals>.<listcomp>  sn     	 	 	U\**	 <>))L##F++ * |=== 	 >==rW   FT)r   )r   r}  retaineds    ` r!   _prune_stale_seeded_entriesr    s[    	 	 	 		 	 	H 8}}G$$uGAAAJ4rW   c                T   d}t                      }t          |           }|rt          |                    d          pd                                          }t          |                    d          pd                                                              d          }t          |                    d          pd                                          }|r<d| }|                    |           |t          || ||t          |||p|d          z  }	 t                      }	|	r|	                    d	          nd
}
t          |
t                    rBt          |
                    d          pd                                                                          }t          |
                    d          pd                                                              d          }d}dD ]V}|
                    |          }t          |t                    r*|                                r|                                } nW|dk    rP|rN|rLt          |          }|| k    r7d}|                    |           |t          || ||t          ||dd          z  }n# t          $ r Y nw xY w||fS )zJSeed a custom endpoint pool from custom_providers config and model config.Fr&   rq   rH   r   rX   zconfig:r  modelNr:   )r&   apicustommodel_config)r{  r   r9   r\   r   r   r|  r_  rv   r"   r   r   r   r   r    )r   r   rp  r}  	cp_configr&   rH   rX   r@   r   	model_cfgmodel_providermodel_base_urlmodel_api_keyrm   r   matched_keys                    r!   _seed_custom_poolr    s   G"uuN ,H55I immI..4"55;;==y}}Z006B77==??FFsKK9==((.B//5577 	%t%%Fv&&&}$!2$+ (!^V 	  G"$$+1;FJJw'''t	i&& 	 z!:!:!@bAAGGIIOOQQN z!:!:!@bAAGGIIPPQTUUNM'  MM!$$a%% !'')) $%GGIIME))n)):>JJ(**+F"&&v...} &,):,9(6%3 	    G     N""s   E?J 
J#"J#c                2     pd                                                                  t                     } fd|D             }                     t                    r)t           |          \  }}|}|t          ||          z  }nSt           |          \  }}t           |          \  }}	|p|}|t          |||	z            z  }|t           |          z  }|r*t           d t          |d           D                        t           |          S )Nrq   c                F    g | ]}t                               |          S rk   )r8   r{   )rg   ra   r:   s     r!   r   zload_pool.<locals>.<listcomp>=  s*    XXX))(G<<XXXrW   c                6    g | ]}|                                 S rk   r   r   s     r!   r   zload_pool.<locals>.<listcomp>N  s     ZZZU]]__ZZZrW   c                    | j         S rS   r   )items    r!   r   zload_pool.<locals>.<lambda>N  s    4= rW   r   )r   r   r   r   r   r  r  r  r  rq  r   r   r   )
r:   raw_entriesr   custom_changedcustom_sourcesrp  singleton_changedsingleton_sourcesenv_changedenv_sourcess
   `         r!   	load_poolr  :  sG   B%%''--//H&x00KXXXXKXXXG-.. 
A):8W)M)M& .wGGG/DXw/W/W,,#1(G#D#D [#2{.w8IK8WXXX-h@@@ 
ZZ&>X>X*Y*Y*YZZZ	
 	
 	
 (G,,,rW   )r   r   )r   r9   r   r9   r   r9   )r   r   r   r>   )r@   r9   r   r   )r   rF   r   r>   )rX   r9   r   r9   rS   )r   r   )rH   r9   r   rB   )r   r   )r   r9   r   r   )r:   r9   r   r9   )
r   r   r:   r9   r@   r9   ra   rP   r   r   )r:   r9   r   r   r   r   )r:   r9   r   r   r   rr  )r   r   r}  r  r   r   )r   r9   r   r   r   rr  )r:   r9   r   r   )K__doc__
__future__r   loggingr*   r   r  rs   r  dataclassesr   r   r   typingr   r   r	   r
   r   r   hermes_constantsr   hermes_cli.authauthr  r   r   r   r   r   r   r   r   r   r   r   r   	getLoggerr_   r  r"   r  r  r  rv   rw   r   rD  r@  rB  r   r   r   r   	frozensetr[   r8   r   r   r   r   r   r   r   r   r   r   r   r_  rq  r  r  r  r  r  rk   rW   r!   <module>r     s   B B " " " " " "         				 2 2 2 2 2 2 2 2 2 2 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 0 0 0 0 0 0 " " " " " "                            
	8	$	$    	  " $ " 	  $  , 
   i      E E E E E E E EP   F F F FU U U U
) ) ) )2 2 2 2
7 7 7 7 7$             R R R R R R R Rj" " " "J   DJ# J# J# J#Z:# :# :# :#z   "=# =# =# =#@- - - - - -rW   