+
    iHàj  ã                  ó–   € R t ^ RIHt ^ RIt^ RIHtHtHtHtH	t	 ]	'       d   ^ RI
Ht RtRtR R ltR R	 ltR
 R lt ! R R4      tR# )a±  Model-scoped rate-limit cooldowns for pooled credentials.

Anthropic enforces its API rate limits (requests / tokens per minute) per
model, so a generic 429 for one Claude model says nothing about the same
credential's standing for its sibling models. Such a 429 is recorded as a
cooldown on the requested model only, beside the credential-wide status that
auth, billing and payment failures keep benching the whole credential with.
)ÚannotationsN)ÚAnyÚDictÚIterableÚOptionalÚTYPE_CHECKING)ÚPooledCredentialÚusage_windowc               ó(   € V ^8„  d   QhRRRRRRRR/# )	é   Úreasonr   Úerror_contextúOptional[dict[str, Any]]Úbilling_unverifiedÚboolÚreturnÚstr© )Úformats   "ÚJ/home/ubuntu/.hermes/hermes-agent/agent/credential_pool_model_cooldowns.pyÚ__annotate__r      s+   € ÷ 	ñ 	 ð 	Ð4Lð 	Ðbfð 	Ðknñ 	ó    c                óÔ   € ^ RI Hp WP                  8X  d(   T;'       g    / P                  R4      '       d   \        # WP                  8X  d   V'       d	   ^ RIHp V# V P                  # )zÄThe pool's failure reason for a rotation (*reason* is a ``FailoverReason``). A usage-window 402
benches only the refused model; an ambiguous billing body is sized as transient, not a 1-hour bench.)ÚFailoverReasonr	   )Ú!FAILURE_REASON_BILLING_UNVERIFIED)Úagent.error_classifierr   ÚbillingÚgetÚFAILURE_REASON_USAGE_WINDOWÚagent.credential_poolr   Úvalue)r   r   r   r   r   s   &&&  r   Úpool_failure_reasonr!      sS   € õ 6Ø×'Ñ'Ô'¨]×-@Ð-@¸b×,EÑ,EÀn×,UÒ,UÜ*Ð*Ø×'Ñ'Ô'×,>ÝKØ0Ð0Ø�<‰<Ðr   c               ó$   € V ^8„  d   QhRRRRRR/# )r   Úentryr   ÚmodelúOptional[str]r   zOptional[float]r   )r   s   "r   r   r   %   s"   € ÷ 
+ñ 
+Ð 0ð 
+¸ð 
+È?ñ 
+r   c                ó`  € V P                   ;'       g    / pV'       g   VP                  4       MVP                  V4      3p\        P                  ! 4       pV Uu. uF4  p\	        V\
        \        34      '       g   K!  WT8”  g   K)  \        V4      NK6  	  ppV'       d   \        V4      # R# u upi )zËActive cooldown blocking *entry* for *model*, or ``None``.

Callers that do not know the model stay conservative: any active model
cooldown blocks them, so an unscoped route cannot reuse the credential.
N)Úmodel_cooldownsÚvaluesr   ÚtimeÚ
isinstanceÚintÚfloatÚmax)r#   r$   Ú	cooldownsr(   ÚnowÚuntilÚactives   &&     r   Úmodel_cooldown_untilr2   %   s†   € ð ×%Ñ%×+Ð+¨€Iß',ˆY×ÑÔ°9·=±=ÀÓ3GÐ2I€FÜ
�)Š)‹+€CÙ(.Ób©˜u´*¸UÄSÌ%ÀL×2QŒlÐV[ÑVaŒlŒe�EŽl©€FÐbß Œ3ˆv‹;Ð* dÐ*ùò cs   ÁB+Á=B+ÂB+c               ó    € V ^8„  d   QhRRRR/# )r   Úmapsr   r   zdict[str, float]r   )r   s   "r   r   r   2   s   € ÷ 	ñ 	 ð 	Ð)9ñ 	r   c            	     ó  € / pV  Fy  p\        V\        4      '       g   K  VP                  4        FJ  w  r4\        V\        \        34      '       g   K#  \        \	        V4      VP                  VR4      4      W&   KL  	  K{  	  V# )uT   Latest reset per model across snapshots â€” each writer only observed its own model.g        )r*   ÚdictÚitemsr+   r,   r-   r   )r4   Úmergedr.   r$   r0   s   *    r   Úmerge_model_cooldownsr9   2   si   € à!€FÛˆ	Ü˜)¤T×*Ò*ÙØ%ŸO™OÖ-‰LˆEÜ˜%¤#¤u ×.Ô.Ü #¤E¨%£L°&·*±*¸UÀCÓ2HÓ I�“ó .ñ ð €Mr   c                  óR   € ] tR t^>tRR/R R lltR R ltRR R lltR	 R
 ltRtR# )Ú CredentialPoolModelCooldownMixinr$   Nc               ó$   € V ^8„  d   QhRRRRRR/# )r   Útokenr   r$   r%   r   r   r   )r   s   "r   r   Ú-CredentialPoolModelCooldownMixin.__annotate__?   s!   € ÷ ñ  cð °]ð Èdñ r   c               ó  aa€ V P                   ;_uu_ 4        \        ;QJ d*    VV3R lV P                   4       F  '       g   K   RM	  RM! VV3R lV P                   4       4      uuRRR4       #   + '       g   i     R# ; i)a   Whether a pool cooldown blocks *token* for *model*.

Closes the paths that hand out a native Anthropic token without
selecting it from the pool (env / borrowed credentials). Tokens the
pool does not know fail open: no row can attribute a cooldown to them.
c              3  ón   <"  € T F*  pVP                   S8H  ;'       d    \        VS4      R Jx € K,  	  R # 5i©N)Úruntime_api_keyr2   )Ú.0r#   r$   r=   s   & €€r   Ú	<genexpr>ÚDCredentialPoolModelCooldownMixin.token_is_blocked.<locals>.<genexpr>G   s<   øé € ð á*�Eð ×%Ñ%¨Ñ.×aÐaÔ3GÈÈuÓ3UÐ]aÐ3aÔaÛ*ùs   ƒ5ž5TFN)Ú_lockÚanyÚ_entries)Úselfr=   r$   s   &fdr   Útoken_is_blockedÚ1CredentialPoolModelCooldownMixin.token_is_blocked?   sL   ù€ ð �Z�Z‹Zß“3õ à!Ÿ]š]ó—3—3’3õ à!Ÿ]š]óó ÷ �Z�Z‹Zús   —+A2Á"A2Á2B	c               ó(   € V ^8„  d   QhRRRRRRRR/# )r   Ústatus_codezOptional[int]r$   r%   Úfailure_reasonr   r   r   )r   s   "r   r   r>   L   s,   € ÷ 
ñ 
Ø(ð
Ø1>ð
ØP]ð
à	ñ
r   c                ó˜   € ^ RI HpHp V'       g   R# VR\        39   d   R# V P                  R8H  ;'       d    VR8H  ;'       d    W4V39  # )z«Anthropic per-model 429s, and a Codex ChatGPT-account model entitlement 400: the
account cannot use *model*, but the credential stays valid for every other model (#71970).)ÚFAILURE_REASON_BILLINGr   FÚmodel_entitlementTÚ	anthropicé­  )r   rP   r   r   Úprovider)rI   rM   r$   rN   rP   r   s   &&&&  r   Ú_is_model_scoped_failureÚ9CredentialPoolModelCooldownMixin._is_model_scoped_failureL   s\   € ÷
 	dçÙØÐ1Ô3NÐOÔOÙà�M‰M˜[Ñ(÷ bð b¨[¸CÑ-?÷ bð bØÐ?`Ð&aÑað	
r   c          
     ó,   € V ^8„  d   QhRRRRRRRRR	R
/# )r   r#   r   r$   r   r   r   rN   r%   r   ÚNoner   )r   s   "r   r   r>   \   s6   € ÷ ñ Ø%ðØ.1ðØBZðà%ðð 
ñr   c                ó:  € ^ RI HpHp VR8X  d"   \        P                  ! 4       \        ,           pMQV! V4      P                  R4      ;'       g3    \        P                  ! 4       V! RV P                  4       R7      ,           pVP                  p\        V P                  4       Fd  p	V	P                  VP                  8w  d   V'       d   V	P                  V8X  g   K9  \        V	P                  W'/4      p
V P                  V	RV
R7       Kf  	  V P                  4        R# )	aÈ  Record a cooldown for *model* on *entry* and every sibling sharing its key.

Same TTL policy as a credential-wide 429 (provider ``reset_at`` wins, a
sole credential keeps its short bench), except a ``model_entitlement``
rejection, which stays benched until the explicit reset path clears it.
Siblings matter because a ``model_config`` twin seeded from the same key
would otherwise be re-selected for the very model that just failed.
Caller holds the lock.
)Ú_exhausted_ttlÚ_normalize_error_contextrQ   Úreset_atrS   ©Úsole_credentialF)Úpersistr'   N)r   rZ   r[   r)   ÚMODEL_ENTITLEMENT_BENCH_SECONDSr   Ú_is_sole_credentialrB   ÚlistrH   Úidr9   r'   Ú_adoptÚ_persist)rI   r#   r$   r   rN   rZ   r[   r0   Ú
failed_keyÚscopedr.   s   &&&&&      r   Ú_cool_down_modelÚ1CredentialPoolModelCooldownMixin._cool_down_model\   sÖ   € ÷ 	SàÐ0Ô0Ü—I’I“KÔ"AÕA‰Eá,¨]Ó;×?Ñ?À
ÓK÷ ð Ü—	’	“™n¨SÀ$×BZÑBZÓB\Ô]Õ]ð ð ×*Ñ*ˆ
Ü˜4Ÿ=™=Ö)ˆFØ�y‰y˜EŸH™HÔ$¯j¸V×=SÑ=SÐWaÔ=aÙÜ-¨f×.DÑ.DÀuÀnÓUˆIØ�K‰K˜¨¸yˆKÖIñ	 *ð
 	�‰Žr   c               ó    € V ^8„  d   QhRRRR/# )r   ÚmodelszIterable[str]r   r   r   )r   s   "r   r   r>   y   s   € ÷ Iñ I -ð IÐ4Lñ Ir   c           
     ó„  € ^ RI HpHp \        P                  ! 4       pV P                  ;_uu_ 4        V P
                   Uu. uF  qUP                  V8w  g   K  VNK  	  pp\        V4      ^8*  pV Uu/ uF+  pV! WWR7      ;p'       g   K  W„8”  g   K  VP                  VbK-  	  p	pV'       dA   \        V	4      \        V4      8X  d(   RRR\        V	P                  4       4      /uuRRR4       # V Uu. uF  qUP                  V	9  g   K  VNK  	  p
p/ pV Fk  pV
 Uu. uF  p\        W\4      NK  	  ppV'       g   K'  \        V4      '       g   K:  \        V4      V,
          \        ^,          8  g   K^  \        V4      W¼&   Km  	  RRR4       X'       d   RRRV/# R# u upi u upi u upi u upi   + '       g   i     L4; i)a  What a picker should say about this pool's rate limits, or ``None`` when nothing is limited.

``{"scope": "account", "resets_at": epoch}`` when every live entry is benched credential-wide
(the whole login is out; another model won't help), else ``{"scope": "models", "models":
{model: epoch}}`` for the given *models* no usable entry can serve until a model cooldown
ends. Entitlement benches (a year: the plan lacks the model) aren't windows that reset, so
they're left out. Read-only: never clears or persists a cooldown.
)ÚSTATUS_DEADÚ_exhausted_untilr]   ÚscopeÚaccountÚ	resets_atNrk   )r   rm   rn   r)   rF   rH   Úlast_statusÚlenrc   Úminr(   r2   Úallr`   )rI   rk   rm   rn   r/   r#   ÚliveÚsoler0   ÚbenchedÚusableÚcooledr$   Úwaitss   &&            r   Úlimit_stateÚ,CredentialPoolModelCooldownMixin.limit_statey   sw  € ÷ 	Hä�iŠi‹kˆØ�Z�Z‹ZØ'+§}¢}ÓY¡}˜e×8IÑ8IÈ[Ñ8X—E�E¡}ˆDÐYÜ�t“9 ‘>ˆDÙ48ó d±D¨5Ù$4°UÔ$QÐQ˜5ÓQô 'ØW\ÑWbô '�u—x‘x ’±DˆGð dçœ˜G›¬¨D«	Ô1Ø ¨K¼¸W¿^¹^Ó=MÓ9NÐO÷ ŠZñ *.ÓI© ·±ÀÑ1H—e�e©ˆFÐIØ')ˆFÛ�ÙIOÓPÉÀÔ-¨eÖ;É�ÐPß‘5œS ŸZœZ¬C°«J¸Õ,<Ô?^ÐabÕ?bÖ,bÜ$'¨£J�F“Mñ  ÷ ÷ 9?�˜ 8¨VÐ4ÐHÀDÐHùò Zùòdùò Jùò Q÷ �Zúsq   ²F/ÁFÁFÁF/Á2F Â
F ÂF Â#?F/Ã-F/Ã1F%ÄF%ÄF/ÄF*
Ä/F/Ä;F/ÅF/Å2F/ÆF/Æ/F?	r   rA   )	Ú__name__Ú
__module__Ú__qualname__Ú__firstlineno__rJ   rU   rh   r|   Ú__static_attributes__r   r   r   r;   r;   >   s$   † ðÀT÷ õ
÷ ÷:Iñ Ir   r;   i€3á)Ú__doc__Ú
__future__r   r)   Útypingr   r   r   r   r   r   r   r`   r   r!   r2   r9   r;   r   r   r   Ú<module>r†      sK   ðñõ #ã ß ?Õ ?çÝ6ð #5Ð ð -Ð õ	õ
+õ	÷TIó TIr   