
    i                   f   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	Z	ddl
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 ddlmZ ddl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+  ej,        e-          Z.dPdZ/dZ0dZ1dZ2dZ3dZ4dZ5dZ6dZ7dZ8e5e6e7e8hZ9dZ:dZ;dZ< e=h d          Z>e G d d                      Z?dQdZ@dRd"ZAdSd%ZBdTd(ZCdUd,ZDdVd.ZEdWd2ZFdXd4ZGdYd6ZHdZd[d8ZId\d;ZJd]d=ZKd^d?ZLd_dAZMdBZN G dC dD          ZOd`dFZPdadGZQdbdIZRdbdJZSdcdMZTdddNZUdedOZVdS )fz<Persistent multi-credential pool for same-provider failover.    )annotationsN)	dataclassfieldsreplacedatetime)AnyDictListOptionalSetTuple)OPENROUTER_BASE_URL)get_env_valueload_env)'CODEX_ACCESS_TOKEN_REFRESH_SKEW_SECONDS!DEFAULT_AGENT_KEY_MIN_TTL_SECONDSPROVIDER_REGISTRY_auth_store_lock_codex_access_token_is_expiring_decode_jwt_claims_load_auth_store_load_provider_state_resolve_kimi_base_url_resolve_zai_base_url_save_auth_store_save_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    :/home/ubuntu/.hermes/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  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                     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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_statusOptional[float]last_status_atOptional[int]last_error_codelast_error_reasonlast_error_messagelast_error_reset_at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)r[   selfs    r'   __post_init__zPooledCredential.__post_init__t   s    :DJJJ     namec                    |t           v r| j                            |          S t          dt	          |           j         d|          )N'z' object has no attribute )_EXTRA_KEYSr[   getAttributeErrortype__name__)r_   rb   s     r'   __getattr__zPooledCredential.__getattr__x   sJ    ;:>>$'''Xd!4XXPTXXYYYra   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@   rb   .0fs     r'   	<setcomp>z-PooledCredential.from_dict.<locals>.<setcomp>   s&    KKK!af
6J6Jqv6J6J6Jra   c                D    i | ]}|v |                     |          S  )rf   rq   krk   s     r'   
<dictcomp>z.PooledCredential.from_dict.<locals>.<dictcomp>   s*    GGGa!w,,7;;q>>,,,ra   c                :    i | ]}|v |         ||         S r]   ru   rv   s     r'   rx   z.PooledCredential.from_dict.<locals>.<dictcomp>   s1    ___1qG||PQ
H^GAJH^H^H^ra   r[   rA      rB   rF   rC   rE   r   rG    r@   ru   )	r   re   
setdefaultuuiduuid4hexrf   AUTH_TYPE_API_KEYSOURCE_MANUAL)clsr@   rk   field_namesdatar[   s     `   r'   	from_dictzPooledCredential.from_dict}   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----ra   c                    h d}i }t          |           D ]6}|j        dv rt          | |j                  }|	|j        |v r
|||j        <   7| j                                        D ]\  }}||||<   |S )N>   rJ   rL   rN   rO   rP   rQ   )r@   r[   )r   rb   getattrr[   items)r_   _ALWAYS_EMITresult	field_defvaluerw   vs          r'   to_dictzPooledCredential.to_dict   s    
 
 
 "$ 	/ 	/I~!666D).11E INl$B$B).y~&J$$&& 	 	DAq}q	ra   c                ~    | j         dk    rt          | j        p| j        pd          S t          | j        pd          S )Nnousr{   )r@   r?   rW   rG   r^   s    r'   runtime_api_keyz PooledCredential.runtime_api_key   sB    =F""t~@):@bAAA4$*+++ra   c                B    | j         dk    r| j        p| j        S | j        S )Nr   )r@   rV   rR   r^   s    r'   runtime_base_urlz!PooledCredential.runtime_base_url   s'    =F""*;dm;}ra   )rb   r?   )r@   r?   rk   rZ   r    rl   )r    rZ   )r    r?   )r    rH   )ri   
__module____qualname____annotations__rI   rJ   rL   rN   rO   rP   rQ   rR   rS   rT   rU   rV   rW   rX   rY   r[   r`   rj   classmethodr   r   propertyr   r   ru   ra   r'   r>   r>   Z   s        MMMGGGJJJNNNMMMKKK#'M''''!%K%%%%&*N****%)O))))'+++++(,,,,,+/////"H"""" $J$$$$#'M''''"&L&&&&(,,,,,#I####*.....M E      Z Z Z Z
 . . . [.   * , , , X,
    X  ra   r>   tokenr?   fallbackc                    t          |           }dD ]V}|                    |          }t          |t                    r*|                                r|                                c S W|S )N)emailpreferred_usernameupn)r   rf   
isinstancer?   strip)r   r   claimskeyr   s        r'   label_from_tokenr      sh    &&F5 ! !

3eS!! 	!ekkmm 	!;;==   Ora   entriesList[PooledCredential]rD   c                >    t          d | D             d          dz   S )Nc              3  $   K   | ]}|j         V  d S r]   rE   rq   entrys     r'   	<genexpr>z!_next_priority.<locals>.<genexpr>   s$      445444444ra   )default   )max)r   s    r'   _next_priorityr      s)    44G444bAAAAEEra   rF   boolc                    | pd                                                                 }|t          k    p|                    t           d          S )Nr{   :)r   lowerr   
startswith)rF   
normalizeds     r'   _is_manual_sourcer      sJ    ,B%%''--//J&T**?*?=@S@S@S*T*TTra   
error_coderM   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((((ra   r   r	   rK   c                   | | dk    rdS t          | t          t          f          r$t          |           }|dk    rdS |dk    r|dz  n|S t          | t                    r|                                 }|sdS 	 t          |          }n# t
          $ r d}Y nw xY w||dk    r|dz  n|S 	 t          j        |                    dd                    	                                S # t
          $ r Y dS w xY wdS )zBest-effort parse for provider reset timestamps.

    Accepts epoch seconds, epoch milliseconds, and ISO-8601 strings.
    Returns seconds since epoch.
    Nr{   r   l    J)     @@Zz+00:00)
r   rD   floatr?   r   
ValueErrorr   fromisoformatr   	timestamp)r   numericraws      r'   _parse_absolute_timestampr      s;    }t%#u&& L,,a<<4#*->#>#>wGK% kkmm 	4	CjjGG 	 	 	GGG	'.1B'B'B7V##O	)#++c8*D*DEEOOQQQ 	 	 	44	4s$   9B	 	BB+9C% %
C32C3messagec                   | sd S t          j        d| t           j                  }|rTt          |                    d                    }|                    d                                          dk    r|dz  n|S t          j        d| t           j                  }|r"t          |                    d                    S d S )Nz,quotaResetDelay[:\s\"]+(\d+(?:\.\d+)?)(ms|s)r      msr   z?retry\s+(?:after\s+)?(\d+(?:\.\d+)?)\s*(?:sec|secs|seconds|s\b))research
IGNORECASEr   groupr   )r   delay_matchr   	sec_matchs       r'   _extract_retry_delay_secondsr      s     t)KWVXVcddK Qk''**++!,!2!21!5!5!;!;!=!=!E!Euv~~5P	\^egigtuuI )Y__Q''(((4ra   error_contextOptional[Dict[str, Any]]rZ   c                   t          | t                    si S i }|                     d          }t          |t                    r+|                                r|                                |d<   |                     d          }t          |t                    r+|                                r|                                |d<   |                     d          p)|                     d          p|                     d          }t          |          }|<t          |t                    r't          |          }|t          j                    |z   }|||d<   |S )Nreasonr   reset_at	resets_atretry_until)r   dictrf   r?   r   r   r   time)r   r   r   r   r   parsed_reset_atretry_delay_secondss          r'   _normalize_error_contextr      sK   mT** 	!#Jx((F&# .6<<>> .%||~~
8	**G'3 0GMMOO 0 '
9*%% 	,[))	,]++ 
 099O:gs#;#;:7CC*"ikk,??O"!0
:ra   r   c                    | j         t          k    rd S t          t          | dd                     }||S | j        r| j        t          | j                  z   S d S )NrQ   )rJ   STATUS_EXHAUSTEDr   r   rL   r   rN   )r   r   s     r'   _exhausted_untilr   
  se    ,,,t(8Mt)T)TUUH L#nU5J&K&KKK4ra   rb   c                v    |                                                                                      dd          S )z>Normalize a custom provider name for use as a pool key suffix. -)r   r   r   ro   s    r'   _normalize_custom_pool_namer     s,    ::<<''S111ra   configc              #    K   | t                      } | dS |                     d          }t          |t                    s$	 ddlm}  ||           }n# t          $ r Y dS w xY w|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_providersr   )get_compatible_custom_providersrb   )
r(   rf   r   listr%   r   r&   r   r?   r   )r   r   r   r   rb   s        r'   _iter_custom_providersr     s     ~"$$~zz"455&-- 	IIIIII>>vFF 	 	 	FF	 ! 7 7%&& 	yy  $$$ 	)$//666667 7s   A 
A"!A"rR   rH   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/rR   r{   )r   rstripr   r?   rf   CUSTOM_POOL_PREFIX)rR   normalized_url	norm_namer   	entry_urls        r'   get_custom_provider_pool_keyr   4  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4ra   	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 r]   )r   r   r   rf   r   )rq   r   	pool_datas     r'   r   z-list_custom_pool_providers.<locals>.<genexpr>F  sx        >>,-- y}}S))400 cN	     ra   )r   sorted)r   s   @r'   list_custom_pool_providersr   C  sH    $T**I          ra   pool_keyc                    |                      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   N  so    122 tc,--../F244  	5LLL 4ra   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_strategiesr{   )	r(   STRATEGY_FILL_FIRSTrf   r   r   r?   r   r   SUPPORTED_POOL_STRATEGIES)r@   r   
strategiesstrategys       r'   get_pool_strategyr  Y  s      F~""899Jj$'' #"":>>(B//5266<<>>DDFFH,,,ra   r   c                      e Zd Zd:dZd;dZd;d	Zd<d
Zd=dZd>dZd?dZ		 d@dAdZ
dBdZdBdZdBdZdCdZdDdZdEd Zd=d!Zd"d"d#dFd&Zd=d'Zd=d(Zdd)dGd*Zd@dHd-ZdId.Zd=d/Zd=d0ZdJd2ZdKd4ZdLd8ZdBd9ZdS )MCredentialPoolr@   r?   r   r   c                    || _         t          |d           | _        d | _        t	          |          | _        t          j                    | _        i | _	        t          | _        d S )Nc                    | j         S r]   r   r   s    r'   <lambda>z)CredentialPool.__init__.<locals>.<lambda>o  s    %. ra   r   )r@   r   _entries_current_idr  	_strategy	threadingLock_lock_active_leases%DEFAULT_MAX_CONCURRENT_PER_CREDENTIAL_max_concurrent)r_   r@   r   s      r'   __init__zCredentialPool.__init__m  s]     w,H,HIII*.*844^%%
.0Dra   r    r   c                *    t          | j                  S r]   )r   r  r^   s    r'   has_credentialszCredentialPool.has_credentialsv      DM"""ra   c                D    t          |                                           S )zCTrue if at least one entry is not currently in exhaustion cooldown.)r   _available_entriesr^   s    r'   has_availablezCredentialPool.has_availabley  s    D++--...ra   c                *    t          | j                  S r]   )r   r  r^   s    r'   r   zCredentialPool.entries}  r  ra   Optional[PooledCredential]c                X      j         sd S t           fd j        D             d           S )Nc              3  <   K   | ]}|j         j        k    |V  d S r]   )rA   r  rq   r   r_   s     r'   r   z)CredentialPool.current.<locals>.<genexpr>  s2      VVuTEU9U9UU9U9U9U9UVVra   )r  nextr  r^   s   `r'   currentzCredentialPool.current  s;     	4VVVVVVVX\]]]ra   oldr>   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  rA   )r_   r#  r$  idxr   s        r'   _replace_entryzCredentialPool._replace_entry  sP    #DM22 	 	JCx36!!%(c" "	 	ra   c                N    t          | j        d | j        D                        d S )Nc                6    g | ]}|                                 S ru   r   r   s     r'   
<listcomp>z+CredentialPool._persist.<locals>.<listcomp>  s     888U]]__888ra   )r   r@   r  r^   s    r'   _persistzCredentialPool._persist  s6    M88$-888	
 	
 	
 	
 	
ra   Nr   status_coderM   r   r   c                B   t          |          }t          |t          t          j                    ||                    d          |                    d          |                    d                    }|                     ||           |                                  |S )Nr   r   r   rJ   rL   rN   rO   rP   rQ   )r   r   r   r   rf   r)  r.  )r_   r   r/  r   normalized_errorupdateds         r'   _mark_exhaustedzCredentialPool._mark_exhausted  s     4MBB(9;;'.228<</33I>> 0 4 4Z @ @
 
 
 	E7+++ra   c           	     (   | j         dk    s|j        dk    r|S 	 ddlm}  |            }|s|S |                    dd          }|                    dd          }|                    dd          }|rm||j        k    rbt                              d	|j                   t          ||||d
d
d
          }| 
                    ||           |                                  |S n2# t          $ r%}t                              d|           Y d
}~nd
}~ww xY w|S )a  Sync a claude_code pool entry from ~/.claude/.credentials.json if tokens differ.

        OAuth refresh tokens are single-use. When something external (e.g.
        Claude Code CLI, or another profile's pool) refreshes the token, it
        writes the new pair to ~/.claude/.credentials.json. The pool entry's
        refresh token becomes stale. This method detects that and syncs.
        	anthropicclaude_coder   )read_claude_code_credentialsrefreshTokenr{   accessToken	expiresAtzKPool entry %s: syncing tokens from credentials file (refresh token changed)NrG   rI   rT   rJ   rL   rN   z(Failed to sync from credentials file: %s)r@   rF   agent.anthropic_adapterr8  rf   rI   loggerdebugrA   r   r)  r.  r&   )	r_   r   r8  credsfile_refreshfile_accessfile_expiresr3  excs	            r'   +_sync_anthropic_entry_from_credentials_filez:CredentialPool._sync_anthropic_entry_from_credentials_file  s\    =K''5<=+H+HL	JLLLLLL0022E  99^R88L))M266K 99[!44L 0C C Cjlqltuuu!!,".". $#'$(   ##E7333 	J 	J 	JLLCSIIIIIIII	Js   C  B0C   
D*D

Dc           	     ^   | j         dk    s|j        dk    r|S 	 t                      5  t                      }t	          |d          }ddd           n# 1 swxY w Y   t          |t                    s|S |                    d          }t          |t                    s|S |                    dd          }|                    dd          }|j        pd}|j	        pd}|r||k    s|r||k    rt                              d|j                   ||p|j	        ddddddd	}	|                    d
          r|d
         |	d
<   t          |fi |	}
|                     ||
           |                                  |
S n2# t           $ r%}t                              d|           Y d}~nd}~ww xY w|S )u  Sync a Codex device_code pool entry from auth.json if tokens differ.

        When a Codex OAuth access token expires (or the ChatGPT account hits
        its 5h/weekly quota), the pool entry gets marked ``STATUS_EXHAUSTED``
        with a ``last_error_reset_at`` that can be many hours in the future.
        Meanwhile the user may run ``hermes model`` / ``hermes auth`` which
        performs a fresh device-code login and writes new tokens to
        ``auth.json`` under ``_auth_store_lock``.  Without this sync the pool
        entry stays frozen until ``last_error_reset_at`` elapses — even
        though fresh credentials are sitting on disk — and every request
        fails with "no available entries (all exhausted or empty)".

        Mirrors the Nous/Anthropic resync paths above.  Only applies to
        device_code-sourced entries; env/API-key-sourced entries have no
        auth.json shadow to sync from.
        openai-codexdevice_codeNtokensrG   r{   rI   zQPool entry %s: syncing Codex tokens from auth.json (refreshed by another process))rG   rI   rJ   rL   rN   rO   rP   rQ   rU   z-Failed to sync Codex entry from auth.json: %s)r@   rF   r   r   r   r   r   rf   rG   rI   r>  r?  rA   r   r)  r.  r&   )r_   r   
auth_storestaterI  store_accessstore_refreshentry_accessentry_refreshfield_updatesr3  rD  s               r'   !_sync_codex_entry_from_auth_storez0CredentialPool._sync_codex_entry_from_auth_store  s[   " =N**elm.K.KL*	O!## I I-//
,ZHHI I I I I I I I I I I I I I I eT** YYx((Ffd++ !::nb99L"JJ;;M !-3L!/52M ,,! -&3}&D&D5H   %1%2%Ie6I#'&*'+)-*.+/	1 	1 99^,, J49.4IM.1!%99=99##E7333 	O 	O 	OLLH#NNNNNNNN	OsG   E; AE; AE; AE; 5+E; !CE; ;
F*F%%F*c                   | j         dk    s|j        dk    r|S 	 t                      5  t                      }t	          |d          }ddd           n# 1 swxY w Y   |s|S |                    dd          }|                    dd          }|r$||j        k    rt                              d|j	                   ||dddd}|                    d	          r|d	         |d	<   |                    d
          r|d
         |d
<   |                    d          r|d         |d<   |                    d          r|d         |d<   t          |j                  }dD ]}|                    |          }	|	|	||<   t          |fd|i|}
|                     ||
           |                                  |
S n2# t          $ r%}t                              d|           Y d}~nd}~ww xY w|S )a  Sync a Nous pool entry from auth.json if tokens differ.

        Nous OAuth refresh tokens are single-use.  When another process
        (e.g. a concurrent cron) refreshes the token via
        ``resolve_nous_runtime_credentials``, it writes fresh tokens to
        auth.json under ``_auth_store_lock``.  The pool entry's tokens
        become stale.  This method detects that and adopts the newer pair,
        avoiding a "refresh token reuse" revocation on the Nous Portal.
        r   rH  NrI   r{   rG   zIPool entry %s: syncing tokens from auth.json (Nous refresh token changed))rG   rI   rJ   rL   rN   rS   rW   rX   rV   r7   r5   r8   r;   r:   r<   r[   z,Failed to sync Nous entry from auth.json: %s)r@   rF   r   r   r   rf   rI   r>  r?  rA   r   r[   r   r)  r.  r&   )r_   r   rJ  rK  rM  rL  rP  extra_updates	extra_keyvalr3  rD  s               r'    _sync_nous_entry_from_auth_storez/CredentialPool._sync_nous_entry_from_auth_store  s    =F""elm&C&CL(	N!## A A-//
,Z@@A A A A A A A A A A A A A A A  !IIor::M 99^R88L %2E!E!E_H  
 %1%2#'&*'+1 1 99\** F272EM,/99[)) D16{1CM+.99344 Z<ABX<YM"8999122 V:?@T:UM"67 $U[ 1 1"; 7 7I  ))I..C36i0!%NN}NNN##E7333 	N 	N 	NLLGMMMMMMMM	NsA   F6 AF6 AF6 AF6 "EF6 6
G% G  G%c                $   |j         dk    rdS 	 t                      5  t                      }| j        dk    rt	          |d          }|	 ddd           dS |j        |d<   |j        r
|j        |d<   |j        r
|j        |d<   |j        r
|j        |d<   |j	        r
|j	        |d<   d	D ]#}|j
                            |          }||||<   $|j        r
|j        |d
<   t          |d|           n| j        dk    rt	          |d          }t          |t                    s	 ddd           dS |                    d          }t          |t                    s	 ddd           dS |j        |d<   |j        r
|j        |d<   |j        r
|j        |d<   t          |d|           n	 ddd           dS t#          |           ddd           dS # 1 swxY w Y   dS # t$          $ r,}t&                              d| j        |           Y d}~dS d}~ww xY w)u  Write refreshed pool entry tokens back to auth.json providers.

        After a pool-level refresh, the pool entry has fresh tokens but
        auth.json's ``providers.<id>`` still holds the pre-refresh state.
        On the next ``load_pool()``, ``_seed_from_singletons()`` reads that
        stale state and can overwrite the fresh pool entry — potentially
        re-seeding a consumed single-use refresh token.

        Applies to any OAuth provider whose singleton lives in auth.json
        (currently Nous and OpenAI Codex).
        rH  Nr   rG   rI   rS   rW   rX   rS  rV   rG  rI  rU   z3Failed to sync %s pool entry back to auth store: %s)rF   r   r   r@   r   rG   rI   rS   rW   rX   r[   rf   rV   r   r   r   rU   r   r&   r>  r?  )r_   r   rJ  rK  rU  rV  rI  rD  s           r'   %_sync_device_code_entry_to_auth_storez4CredentialPool._sync_device_code_entry_to_auth_storeB  sL    <=((F-	d!## *- *--//
=F**0VDDE}*- *- *- *- *- *- *- *- -2,>E.)* E161Do.' ?.3.>l+ =-2_k*1 S8=8R45&? 3 3	 $kooi88?/2E),/ O6;6N23(VUCCCC]n440^LLE%eT22 9*- *- *- *- *- *- *- *-: #YYx00F%fd33 ?*- *- *- *- *- *- *- *-@ .3-?F>** F272E/) C050Bn-(^UKKKK Q*- *- *- *- *- *- *- *-T !,,,U*- *- *- *- *- *- *- *- *- *- *- *- *- *- *- *- *- *-V  	d 	d 	dLLNPTP]_bccccccccc	dsk   G -G
G CGG ,+GG $?G#G 0G?G GG GG 
H#!H

Hforcec               
   |j         t          k    s|j        s|r|                     |d            d S 	 | j        dk    rddlm}  ||j        |j                            d                    }t          ||d         |d         |d         	          }|j        d
k    r[	 ddlm
}  ||d         |d         |d                    n# t          $ r&}t                              d|           Y d }~nid }~ww xY wn_| j        dk    rSt          j        |j        |j                  }t          ||d         |d         |                    d                    }n| j        dk    r|                     |          }||ur|}|j        |j        |j        |j        |j        |j        |j        |j        |j        |j        |j        |j        d}	t          j        |	t<          ||          }i }
t?          |j                   }d tC          |          D             }|"                                D ]\  }}||v r||
|<   |tF          v r|||<   t          |fd|i|
}n|S n# t          $ r}t                              d| j        |j$        |           | j        dk    r|j        d
k    r| %                    |          }|j        |j        k    r4t                              d           	 ddlm}  ||j        |j                            d                    }t          ||d         |d         |d         tL          d d           }| '                    ||           | (                                 	 ddlm
}  ||d         |d         |d                    n2# t          $ r%}t                              d|           Y d }~nd }~ww xY w|cY d }~S # t          $ r%}t                              d|           Y d }~n>d }~ww xY w| )                    |          s!t                              d           |cY d }~S | j        dk    r|                     |          }|j        |j        k    r{t                              d           t          |tL          d d d d d           }| '                    ||           | (                                 | *                    |           |cY d }~S |                     |d            Y d }~d S d }~ww xY wt          |tL          d d d d d           }| '                    ||           | (                                 | *                    |           |S )Nr6  r   )refresh_anthropic_oauth_purehermes_pkce)use_jsonrG   rI   rT   )rG   rI   rT   r7  )_write_claude_code_credentialsz7Failed to write refreshed token to credentials file: %srG  rU   )rG   rI   rU   r   )rG   rI   r4   r9   rV   r6   r3   r7   rS   rW   rX   r2   )min_key_ttl_secondsforce_refresh
force_mintc                    h | ]	}|j         
S ru   ro   rp   s     r'   rs   z0CredentialPool._refresh_entry.<locals>.<setcomp>  s    >>>1>>>ra   r[   z'Credential refresh failed for %s/%s: %sz8Retrying refresh with synced token from credentials filer<  zDFailed to write refreshed token to credentials file (retry path): %szRetry refresh also failed: %sz7Credentials file has valid token, using without refreshu?   Nous refresh failed but auth.json has newer tokens — adoptingr1  )+rC   AUTH_TYPE_OAUTHrI   r4  r@   r=  r\  rF   endswithr   r_  r&   r>  r?  auth_modrefresh_codex_oauth_purerG   rf   rW  r4   r9   rV   r6   r3   r7   rS   rW   rX   r2   refresh_nous_oauth_from_stater   r   r[   r   r   re   rA   rE  	STATUS_OKr)  r.  _entry_needs_refreshrY  )r_   r   rZ  r\  	refreshedr3  r_  wexcsynced
nous_staterP  rT  _field_namesrw   r   rD  	retry_excs                    r'   _refresh_entryzCredentialPool._refresh_entry  s   ?o--U5H- 2$$UD1114I	}++PPPPPP88'"\22=AA  	 "!*>!:"+O"<"+O"<	   <=00fZZZZZZ66%n5%o6%o6   
 % f f f%^`deeeeeeeef 1 .00$=&' 	 "!*>!:"+O"<!*~!>!>	   &((>>uEE&&"E$)$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 }++0M0MII%PP'5+>>>LL![\\\QXXXXXX$@$@"0%+]%;%;M%J%J% % %	 #*")2>)B*3O*D*3O*D(1+/,0# # # ++FG<<<w^^^^^^:: ). 9 )/ : )/ :   
  ) w w w"LL)oquvvvvvvvvw&$ Q Q Q%DiPPPPPPPPQ226:: "LL!Z[[[!MMMMMM }&&>>uEE'5+>>>LL!bccc%$-'+(,*.+/,0  G ''888MMOOO>>wGGG"NNNNNN  ---44444?	B ! "# $
 
 
 	E7+++ 	227;;;s   A+I %C I 
C6C1+I 1C66E#I T'A?S='BO/%NO
ON?:O?OOT
O=O83S=8O==3S=0T6B%S=T!S==T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 )NFr6    i rG  r   )	rC   rd  r@   rT   rD   r   r   rG   r   r_   r   s     r'   rj  z#CredentialPool._entry_needs_refresh!  s    ?o--5=K''"*uu*++s49;;3E/F/F/PPP=N**2"7   =F"" 5ura   c                l    | j         5  |                                 cd d d            S # 1 swxY w Y   d S r]   )r  _select_unlockedr^   s    r'   selectzCredentialPool.select4  s}    Z 	+ 	+((**	+ 	+ 	+ 	+ 	+ 	+ 	+ 	+ 	+ 	+ 	+ 	+ 	+ 	+ 	+ 	+ 	+ 	+   )--Fclear_expiredrefreshrz  r{  c          
     Z   t          j                     }d}g }| j        D ]t}| j        dk    r8|j        dk    r-|j        t
          k    r|                     |          }||ur|}d}| j        dk    r8|j        dk    r-|j        t
          k    r|                     |          }||ur|}d}| j        dk    r8|j        dk    r-|j        t
          k    r|                     |          }||ur|}d}|j        t
          k    rOt          |          }|||k     r|r5t          |t          ddddd	          }	|                     ||	           |	}d}|r2|                     |          r|                     |d
          }
|
]|
}|                    |           v|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).
        Fr6  r7  Tr   rH  rG  Nr1  rZ  )r   r  r@   rF   rJ   r   rE  rW  rQ  r   r   ri  r)  rj  rq  appendr.  )r_   rz  r{  nowcleared_any	availabler   rm  exhausted_untilclearedrk  s              r'   r  z!CredentialPool._available_entries8  s    ikk,.	] 7	$ 7	$E ,,1N1N)-===II%PP&&"E"&K
 ''55)-===>>uEE&&"E"&K //55)-===??FF&&"E"&K $444"25"9"9".33H3H  '%$-'+(,*.+/,0  G ''w777#E"&K "444U;; " //U/CC	$!U#### 	MMOOOra   c                   |                      dd          }|s#d | _        t                              d           d S | j        t
          k    r"t          j        |          j        | _        S | j        t          k    rbt          |          dk    rOt          |d           t          j        dz             }|                     |           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 )NTry  z>credential pool: no available entries (all exhausted or empty)r   c                    | j         S r]   rY   )es    r'   r
  z1CredentialPool._select_unlocked.<locals>.<lambda>  s     ra   r  r  r   c                4    g | ]}|j         j         k    |S ru   rA   )rq   	candidater   s     r'   r-  z3CredentialPool._select_unlocked.<locals>.<listcomp>  s)    \\\Y9<SXS[C[C[yC[C[C[ra   r   c                6    g | ]\  }}t          ||           S r   r   )rq   r(  r  s      r'   r-  z3CredentialPool._select_unlocked.<locals>.<listcomp>  s)    ggg.#yWY===gggra   )r  r  r>  infor  STRATEGY_RANDOMr0   choicerA   STRATEGY_LEAST_USEDr   minr   rY   r)  STRATEGY_ROUND_ROBINr  r~  r'  r.  r"  )r_   r  r3  rotatedr   s       @r'   rv  zCredentialPool._select_unlocked~  s   ++$+MM	 	#DKKXYYY4>_,,M),,E$xDL>000S^^a5G5G	'@'@AAAEe53F3JKKKGw///$xDN>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ra   c                r    |                                  }||S |                                 }|r|d         nd S Nr   )r"  r  )r_   r"  r  s      r'   peekzCredentialPool.peek  s>    ,,..N++--	(2y||d2ra   )r   c                  | j         5  |                                 p|                                 }|	 d d d            d S |j        p|j        d d         }t
                              d||           |                     |||           d | _        |                                 }|r1|j        p|j        d d         }t
                              d|           |cd d d            S # 1 swxY w Y   d S )N   z;credential pool: marking %s exhausted (status=%s), rotatingzcredential pool: rotated to %s)	r  r"  rv  rB   rA   r>  r  r4  r  )r_   r/  r   r   _label
next_entry_next_labels          r'   mark_exhausted_and_rotatez(CredentialPool.mark_exhausted_and_rotate  s`    Z 	 	LLNN=d&;&;&=&=E}	 	 	 	 	 	 	 	 [0EHRaRLFKKM     ]CCC#D..00J K(.C*-2C<kJJJ	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	s   ,C&BC&&C*-C*credential_idrH   c                     j         5  |r; j                            |d          dz    j        |<   | _        |cddd           S                      dd          }|s	 ddd           dS  fd|D             }|r|n|}t          | fd          } j                            |j        d          dz    j        |j        <   |j         _        |j        cddd           S # 1 swxY w Y   dS )	a\  Acquire a soft lease on a credential.

        If a specific credential_id is provided, lease that entry directly.
        Otherwise prefer the least-leased available credential, using priority as
        a stable tie-breaker. When every credential is already at the soft cap,
        still return the least-leased one instead of blocking.
        r   r   NTry  c                f    g | ]-}j                             |j        d           j        k     +|.S )r   )r  rf   rA   r  r   s     r'   r-  z0CredentialPool.acquire_lease.<locals>.<listcomp>  sF       &**58Q77$:NNN NNNra   c                R    j                             | j        d          | j        fS r  )r  rf   rA   rE   )r   r_   s    r'   r
  z.CredentialPool.acquire_lease.<locals>.<lambda>  s#    4#6#:#:58Q#G#G"X ra   r  )r  r  rf   r  r  r  rA   )r_   r  r  	below_cap
candidateschosens   `     r'   acquire_leasezCredentialPool.acquire_lease  s    Z 	 	 %595H5L5L]\]5^5^ab5b#M2#0 $		 	 	 	 	 	 	 	 //dD/QQI 	 	 	 	 	 	 	 	   #,  I '0>YJXXXX  F .2-@-D-DVYPQ-R-RUV-VD	*%yD9+	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	s   1C%C%.A*C%%C),C)c                    | j         5  | j                            |d          }|dk    r| j                            |d           n|dz
  | j        |<   ddd           dS # 1 swxY w Y   dS )z/Release a previously acquired credential lease.r   r   N)r  r  rf   pop)r_   r  counts      r'   release_leasezCredentialPool.release_lease  s    Z 	? 	?'++M1==Ezz#''t<<<<5:QY#M2	? 	? 	? 	? 	? 	? 	? 	? 	? 	? 	? 	? 	? 	? 	? 	? 	? 	?s   AA  A$'A$c                l    | j         5  |                                 cd d d            S # 1 swxY w Y   d S r]   )r  _try_refresh_current_unlockedr^   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 	8rx  c                    |                                  }|d S |                     |d          }||j        | _        |S )NTr}  )r"  rq  rA   r  )r_   r   rk  s      r'   r  z,CredentialPool._try_refresh_current_unlocked  sG    =4''T'::	 (|Dra   rD   c                   d}g }| j         D ][}|j        s|j        s|j        r/|                    t          |d d d d d d                      |dz  }F|                    |           \|r|| _         |                                  |S )Nr   r1  r   )r  rJ   rL   rN   r~  r   r.  )r_   r  new_entriesr   s       r'   reset_statuseszCredentialPool.reset_statuses  s    ] 	* 	*E  *E$8 *E<Q *""$('+(,*.+/,0  
 
 
 
""5)))) 	'DMMMOOOra   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  )rq   new_priorityr   s      r'   r-  z/CredentialPool.remove_index.<locals>.<listcomp>  s9     
 
 
#e EL111
 
 
ra   )r   r  r  r'  r.  r  rA   )r_   r  removeds      r'   remove_indexzCredentialPool.remove_index
  s    199DM 2 2224-##EAI..
 
'0'?'?
 
 
 	wz))#Dra   targetr	   ?Tuple[Optional[int], Optional[PooledCredential], Optional[str]]c                ^   t          |pd                                          sdS t          | j        d          D ]\  }}|j        k    r||d fc S fdt          | j        d          D             }t          |          dk    r|d         d         |d         d         d fS t          |          dk    r	d d d dfS                                 rMt                    }d|cxk    rt          | j                  k    rn n|| j        |dz
           d fS d d d	| d
fS d d d dfS )Nr{   )NNzNo credential target provided.r   )startc                    g | ]J\  }}|j                                                                                                         k    F||fKS ru   )rB   r   r   )rq   r(  r   r   s      r'   r-  z1CredentialPool.resolve_target.<locals>.<listcomp>   sX     
 
 
U{  ""((**ciikk99 %L999ra   r   zAmbiguous credential label "z-". Use the numeric index or entry id instead.zNo credential #.zNo credential matching "z".)r?   r   r'  r  rA   r   isdigitrD   )r_   r  r(  r   label_matchesr  r   s         @r'   resolve_targetzCredentialPool.resolve_target  s   &,B%%'' 	@??#DM;;; 	( 	(JCx3E4'''' 
 
 
 
'Q???
 
 

 }"" #A&a(8(;TAA}!!pcppppp;;== 	:HHEE////S///////dmEAI6<<999999T=c=====ra   c                    t          |t          | j                            }| j                            |           |                                  |S )Nr   )r   r   r  r~  r.  rt  s     r'   	add_entryzCredentialPool.add_entry0  sF    t}(E(EFFFU###ra   )r@   r?   r   r   )r    r   )r    r   )r    r  )r#  r>   r$  r>   r    r%  )r    r%  r]   )r   r>   r/  rM   r   r   r    r>   )r   r>   r    r>   )r   r>   r    r%  )r   r>   rZ  r   r    r  )r   r>   r    r   )rz  r   r{  r   r    r   )r/  rM   r   r   r    r  )r  rH   r    rH   )r  r?   r    r%  )r    rD   )r  rD   r    r  )r  r	   r    r  )ri   r   r   r  r  r  r   r"  r)  r.  r4  rE  rQ  rW  rY  rq  rj  rw  r  rv  r  r  r  r  r  r  r  r  r  r  ru   ra   r'   r  r  l  s~       E E E E# # # #/ / / /# # # #^ ^ ^ ^
   
 
 
 
 37	    (# # # #J> > > >@5 5 5 5n;d ;d ;d ;dz` ` ` `D   &+ + + + ;@QV D D D D D DL   B3 3 3 3 37	     .    >? ? ? ?8 8 8 8      0   > > > >2     ra   r  rk   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 )
NrA   rz   rE   rB   Tc                    h | ]	}|j         
S ru   ro   rp   s     r'   rs   z _upsert_entry.<locals>.<setcomp>H  s    555qAF555ra   >   rA   rE   r[   F)r'  rF   r|   r}   r~   r   r   rf   r~  r>   r   r   r   rB   r   re   r[   r   )r   r@   rF   rk   existing_idxr(  r   existingrP  rT  ro  r   r   s                r'   _upsert_entryr  7  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5ra   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 )Nr6  Fr   r   r         )zenv:ANTHROPIC_TOKENzenv:CLAUDE_CODE_OAUTH_TOKENr]  r7  zenv:ANTHROPIC_API_KEYc              3  B   K   | ]}t          |j                  |V  d S r]   r   rF   r   s     r'   r   z-_normalize_pool_priorities.<locals>.<genexpr>h  s2      GG5'8'F'FGGGGGGGra   c                    | j         S r]   r   r	  s    r'   r
  z,_normalize_pool_priorities.<locals>.<lambda>i  s    %. ra   r  c              3  B   K   | ]}t          |j                  |V  d S r]   r  r   s     r'   r   z-_normalize_pool_priorities.<locals>.<genexpr>l  s2      KK5+<U\+J+JKKKKKKKra   c                n                         | j        t                              | j        | j        fS r]   )rf   rF   r   rE   rB   )r   source_ranks    r'   r
  z,_normalize_pool_priorities.<locals>.<lambda>m  s/    OOEL#k*:*:;;NK
 ra   c                $    i | ]\  }}|j         |S ru   r  )rq   r(  r   s      r'   rx   z._normalize_pool_priorities.<locals>.<dictcomp>u  s     DDD:33DDDra   r   T)r   r'  rE   r   rA   )
r@   r   manual_entriesseeded_entriesordered	id_to_idxchangedr  r   r  s
            @r'   _normalize_pool_prioritiesr  \  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Nra   Tuple[bool, Set[str]]c                P   d}t                      }t                      }	 ddlm} n# t          $ r d }Y nw xY w| dk    r	 ddlm}  |d          s||fS n# t          $ r Y nw xY wddlm}m} d |            fd	 |            ffD ]\  }	}
|
r|
	                    d
          r || |	          r)|
                    |	           |t          || |	|	t          |
	                    d
d          |
	                    d          |
	                    d          t          |
	                    d
d          |	          d          z  }n| dk    rTt          |d          }|r? || d          s2|
                    d           t          |	                    d          pd                                          }|p#t          |	                    dd          d          }|t          || di dddt          d|	                    dd          d|	                    d          d|	                    d          d|	                    d          d|	                    d          d|	                    d          d|	                    d          d|	                    d          d|	                    d          d|	                    d          d|	                    d          d|	                    d          d |	                    d           d!|	                    d!          d"|	                    d"          |	                    d#          t#          |	                    d$          t$                    r|	                    d$          nd |d%          z  }n| d&k    r	 dd'lm}m}  |            \  }}|r ||          }d(|                                v rd)nd*| }	 || |	          sR|
                    |	           t/          j	        |           }|t          || |	|	t0          ||r|j        nd|d+          z  }n# t4          $ r&}t6                              d,|           Y d }~nd }~ww xY w| d-k    r	 dd.lm}  |d/          }
|
	                    d0d          }|r|
	                    dd1          }	 || |	          sq|
                    |	           |t          || |	|	t          ||
	                    d2          |
	                    d3d          |
	                    d4|	          d5          z  }n# t4          $ r&}t6                              d6|           Y d }~nd }~ww xY w| d7k    r	 dd8lm}  |d7          }|rP|	                    d          r:d9}	 || |	          s+|
                    |	           d }	 dd:lm} |	                    dd          }|r7tA          |!                    |          "                                d;z            }n# t4          $ r d }Y nw xY wt          |	                    dd          pd          #                    d<          }|t          || |	|	t          |d         |	                    d          |||	                    dd          p#t          |	                    dd          |	          d=          z  }nC# t4          $ r&}t6                              d>|           Y d }~nd }~ww xY w| d?k    r	 || d          r||fS t          |d?          }t#          |t$                    r|	                    d@          nd }t#          |t$                    r|	                    d          r|
                    d           |t          || ddt          |	                    dd          |	                    d          dA|	                    dB          t          |	                    dd          d          dC          z  }||fS )DNFr   is_source_suppressedc                    dS NFru   _p_ss     r'   _is_suppressedz-_seed_from_singletons.<locals>._is_suppressed      5ra   r6  )!is_provider_explicitly_configured)r8  read_hermes_oauth_credentialsr]  r7  r:  r{   r9  r;  )rF   rC   rG   rI   rT   rB   r   rH  rB   rG   rF   rC   rI   rS   r6   r3   r4   r9   rV   rW   rX   r7   r5   r8   r;   r:   r<   r2   )r<   r2   rB   copilot)resolve_copilot_tokenget_copilot_api_tokenghgh_clienv:rF   rC   rG   rR   rB   zCopilot token seed failed: %sz
qwen-oauth) resolve_qwen_runtime_credentials)refresh_if_expiringr,   zqwen-clirT   rR   	auth_file)rF   rC   rG   rT   rR   rB   z Qwen OAuth token seed failed: %szminimax-oauth)get_provider_auth_stater+   r   rs  r   )rF   rC   rG   rI   rT   rR   rB   z#MiniMax OAuth token seed failed: %srG  rI  z%https://chatgpt.com/backend-api/codexrU   )rF   rC   rG   rI   rR   rU   rB   )$setr   hermes_cli.authr  ImportErrorr  r=  r8  r  rf   addr  rd  r   r   r?   r   r   r   hermes_cli.copilot_authr  r  r   r   r   rV   r&   r>  r?  r  r  r   rD   r   r   r   )r@   r   r  active_sourcesrJ  r  r  r8  r  source_namer@  rK  custom_labelseeded_labelr  r  r   rF   	api_tokenpconfigrD  r  r  rT   _dtr   rR   rI  s                               r'   _seed_from_singletonsr  ~  s.
   G"uuN!##JJJJJJJJ   	 	 	 	 	 ;
	IIIIII44[AA /../ 	 	 	D	 	hggggggg 99;;<88::;#
 	 	K  =11 !>(K88 "";///="-%4(-		-(D(D).>)B)B).;)?)?!1%))M22N2NP[!\!\ 	  	, 
V		$Z88 *	-@@ *	}---
 uyy117R88>>@@L' +;		."--}, ,L }m #EIInb$A$A $UYY%?%?	
 !%))L"9"9 !%))L"9"9 UYYw//  ;!7!7 &uyy1B'C'C )%))4H*I*I  ;!7!7 +EII6L,M,M& "599]#;#;'( !%))L"9"9)* #EIIn$=$=+, +EII6L,M,M-. '		2D(E(E/0 .3YY7N-O-O/9%))E:J:JD/Q/Q[599U+++W[)5  	     GD 
Y			?\\\\\\\\1133ME6 11%88	*.&,,..*@*@hhoVoo%~h<< "&&{333/3H==G} #&1):,5FM(U(B(BSU%+ 	    G  	? 	? 	?LL8#>>>>>>>>	? 
\	!	!	BHHHHHH44OOOEIIi,,E #ii*==%~h<< "&&{333} #&1)8,1-2YY-G-G(-		*b(A(A%*YY{K%H%H 	    G  	B 	B 	BLL;SAAAAAAAA	B 
_	$	$!	E??????++O<<E >22 %%~h<< "&&{333$(M-<<<<<<#iib99 [,/0A0A#0F0F0P0P0R0RUY0Y,Z,ZM$ - - -(,-"599-A2#F#F#L"MMTTUXYYH} #&1)8,1.,A-2YY-G-G-:(0%*YYw%;%; &?O %		." = ={@ @
 
	    G   	E 	E 	ELL>DDDDDDDD	E 
^	#	#
 >(M22 	+N**$Z@@(25$(?(?I8$$$T fd## 	

>(B(B 	}---}+!0$*JJ~r$B$B%+ZZ%@%@ G$)IIn$=$=-fjj.L.Lm\\ 	  G N""s   ' 77A 
A%$A%(BQ 
Q7Q22Q7B=U   
U0
U++U0;A[! AX" ![! "X1.[! 0X11B.[! !
\+\\c                   d}t                      }dd}	 ddlm} n# t          $ r d }Y nw xY w| d	k    r] |d
          }|rLd} || |          r||fS |                    |           |t          || ||t          |t          d
d          z  }||fS t          j	        |           }|r|j
        t          k    r||fS d}	|j        r# ||j                                      d          }	t          |j                  }
| dk    rg d}
|
D ]} ||          }|sd| } || |          r"|                    |           | dk    r|                    d          st           nt          }|	p|j        }| dk    rt%          ||j        |	          }n| dk    rt'          ||j        |	          }|t          || ||||||d          z  }||fS )NFr   r?   r    c                    t                      }|                    |           p t          j                            |           pd}|                                S )Nr{   )r   rf   osenvironr   )r   env_filerV  s      r'   _get_env_prefer_dotenvz._seed_from_env.<locals>._get_env_prefer_dotenvm  sB    ::ll3<2:>>##6#6<"yy{{ra   r   r  c                    dS r  ru   r  s     r'   _is_source_suppressedz-_seed_from_env.<locals>._is_source_suppressedz  r  ra   
openrouterOPENROUTER_API_KEYzenv:OPENROUTER_API_KEYr  r{   r   r6  )ANTHROPIC_TOKENCLAUDE_CODE_OAUTH_TOKENANTHROPIC_API_KEYr  z
sk-ant-apizkimi-codingzai)r   r?   r    r?   )r  r  r  r  r  r  r   r   r   rf   rC   base_url_env_varr   r   api_key_env_varsr   rd  rV   r   r   )r@   r   r  r  r  r  r   rF   r  env_urlenv_varsenv_varrC   rR   s                 r'   _seed_from_envr  e  s   G"uuN   QQQQQQQ   	 	 	 	 	 <&&';<< 	-F$$Xv66 /..v&&&}$!2$) 31 	  G &&#H--G 'g'+<<<&&G O(()ABBII#NNG,--H;
 
 
  
 
&&w// 	!!!  622 	6"""'/;'>'>uGWGWXdGeGe'>OOk|	8g8}$$-eW5OQXYYHH,UG4NPWXXH= & %$  	
 
 	
 N""s    --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  >   r7  r]  )r   rF   r   )rq   r   r  s     r'   r-  z/_prune_stale_seeded_entries.<locals>.<listcomp>  sn     	 	 	U\**	 <>))L##F++ * |=== 	 >==ra   FT)r   )r   r  retaineds    ` r'   _prune_stale_seeded_entriesr    s[    	 	 	 		 	 	H 8}}G$$uGAAAJ4ra   c                   d}t                      }	 ddlm} n# t          $ r d }Y nw xY wt	          |           }|rt          |                    d          pd                                          }t          |                    d          pd                                                              d          }t          |                    d	          pd                                          }|rHd
| }	 || |	          s7|	                    |	           |t          || |	|	t          |||p|	d          z  }	 t                      }
|
r|
                    d          nd}t          |t                    rNt          |                    d          pd                                                                          }t          |                    d          pd                                                              d          }d}dD ]V}|                    |          }t          |t
                    r*|                                r|                                } nW|dk    r\|rZ|rXt!          |          }|| k    rCd}	 || |	          s5|	                    |	           |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   r  c                    dS r  ru   r  s     r'   r  z)_seed_custom_pool.<locals>._is_suppressed  r  ra   r,   r{   rR   r   rb   zconfig:r  modelNr@   )r,   apicustommodel_config)r  r  r  r  r   r?   rf   r   r   r  r  r   r(   r   r   r   r   r&   )r   r   r  r  r  	cp_configr,   rR   rb   rF   r   	model_cfgmodel_providermodel_base_urlmodel_api_keyrw   r   matched_keys                     r'   _seed_custom_poolr!    sA   G"uuNJJJJJJJ   	 	 	 	 	
 ,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!>(F33 ""6***="(%6(/$,!% 	   "$$+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)>(F;; &**6222=#$"*0->0=,:)7 	$ $      N""s    ))=FK	 	
KK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 )Nr{   c                F    g | ]}t                               |          S ru   )r>   r   )rq   rk   r@   s     r'   r-  zload_pool.<locals>.<listcomp>  s*    XXX))(G<<XXXra   c                6    g | ]}|                                 S ru   r,  r   s     r'   r-  zload_pool.<locals>.<listcomp>.  s     ZZZU]]__ZZZra   c                    | j         S r]   r   )items    r'   r
  zload_pool.<locals>.<lambda>.  s    4= ra   r  )r   r   r   r   r   r!  r  r  r  r  r   r   r  )
r@   raw_entriesr   custom_changedcustom_sourcesr  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,,,ra   )r    r!   )r   r?   r   r?   r    r?   )r   r   r    rD   )rF   r?   r    r   )r   rM   r    rD   )r   r	   r    rK   )r   r?   r    rK   )r   r   r    rZ   )r   r>   r    rK   )rb   r?   r    r?   r]   )r   r!   )rR   r?   r    rH   )r    r   )r   r?   r    r   )r@   r?   r    r?   )
r   r   r@   r?   rF   r?   rk   rZ   r    r   )r@   r?   r   r   r    r   )r@   r?   r   r   r    r  )r   r   r  r  r    r   )r   r?   r   r   r    r  )r@   r?   r    r  )W__doc__
__future__r   loggingr  r0   r  r   r}   r   dataclassesr   r   r   r   typingr	   r
   r   r   r   r   hermes_constantsr   r%   r   r   r  authrf  r   r   r   r   r   r   r   r   r   r   r   r   r   r   	getLoggerri   r>  r(   ri  r   rd  r   r   r   r  r  r  r  r   r   r   	frozensetre   r>   r   r   r   r   r   r   r   r   r   r   r   r   r   r  r  r  r  r  r  r  r  r!  r.  ru   ra   r'   <module>r8     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 5 5 5 5 5 5 5 5 " " " " " "                               " 
	8	$	$    	  " $ " 	  $  ' 
   i      O O O O O O O Od   F F F FU U U U
) ) ) )   <
 
 
 
   2   2 2 2 2
7 7 7 7 74              )* %H H H H H H H HV" " " "J   Dd# d# d# d#NX# X# X# X#v   "F# F# F# F#R- - - - - -ra   