+
    iHàj‡2  ã                   ó€  a € R t!0 t R t^ RIt^ RIt^ RIt^ RIt^ RIHt ^ RIHtH	t	 ^ RI
Ht ]P                  ! ]4      t ! R R]4      t]P"                  ! 4       tRs] ^ k ]! 4       t] ^k R R ltR	 R
 ltR R lt ! R R]4      tRRRR/R R llt ! R R]4      tR R ltR R ltR R ltR R ltR R lt R# ) u5  Why an auxiliary client could not be built â€” and the Nous credential failure behind it.

``_resolve_nous_runtime_api`` must swallow the resolver's ``AuthError`` and return None so the
ladder can still fall back (stored token, fallback_chain). Swallowing it at DEBUG left the goal
loop reporting ``judge error: RuntimeError`` while the real cause was an ``invalid_grant`` refresh
(#42177). This module remembers the latest failure so the ladder's raise and the goal judge can
name it, and warns ONCE per distinct message so operators see it without debug logging.
N)Údatetime)ÚAnyÚOptional)Úsafe_strftimec                   ó   € ] tR t^tRtRtR# )ÚAuxiliaryClientUnavailablezQNo auxiliary client could be built for the task (missing credentials / provider).© N©Ú__name__Ú
__module__Ú__qualname__Ú__firstlineno__Ú__doc__Ú__static_attributes__r   ó    Ú@/home/ubuntu/.hermes/hermes-agent/agent/auxiliary_unavailable.pyr   r      s   † Ý[r   r   c                ó0   € V ^8„  d   QhR\         R\         /# ©é   ÚexcÚreturn)ÚBaseException)Úformats   "r   Ú__annotate__r      s   € ÷ ñ ¤ð ´=ñ r   c           	     ó*  € ^ RI HpHp ^ RIHp \
        P                  ! \        4      ;_uu_ 4        T! V! R4      ;'       g    / 4      pV'       dM   VP                  R4      '       d6   V! \        VR,          4      RVP                  R4      RR7      uuRRR4       # RRR4       \        W4      '       dJ   V! \        V 4      V P                  V P                  V P                  V P                  V P                  R	7      # V #   + '       g   i     Ll; i)
uÙ  Prefer the persisted terminal quarantine marker over *exc*; sentence-terminate either message.

The pool rung swallows the real ``invalid_grant`` and wipes the dead tokens, so by the time the
auth-store resolver runs it can only say "No access token found"; the marker it wrote still
carries the message and code the user needs (#42177). ``format_auth_error`` appends the
remediation sentence with a space, so an unterminated message reads "Invalid refresh token Run â€¦".
)Ú	AuthErrorÚget_provider_auth_state)Ú_terminal_quarantine_markerÚnousÚmessageÚcodeT)Úproviderr    Úrelogin_requiredN)r!   r    r"   Úretry_afterÚ	retryable)Úhermes_cli.authr   r   Úhermes_cli.auth_nousr   Ú
contextlibÚsuppressÚ	ExceptionÚgetÚ	_sentenceÚ
isinstancer!   r    r"   r#   r$   )r   r   r   r   Úmarkers   &    r   Ú_quarantined_nous_errorr.      sË   € ÷ CÝ@ä	×	Ò	œY×	'Õ	'Ù,Ñ-DÀVÓ-L×-RÐ-RÐPRÓSˆß�f—j‘j ×+Ò+ÙœY v¨iÕ'8Ó9ÀFÐQW×Q[ÑQ[Ð\bÓQcØ.2ô4÷ 
(×	'Ò	'ô
 �#×!Ò!Ùœ 3›°#·,±,ÀSÇXÁXØ*-×*>Ñ*>ÈCÏOÉOØ#&§=¡=ô2ð 	2ð €J÷ 
(×	'ús   ± DÁDÁ)*DÄD	c                ó0   € V ^8„  d   QhR\         R\        /# )r   Útextr   )ÚobjectÚstr)r   s   "r   r   r   6   s   € ÷ /ñ /”Fð /œsñ /r   c                 ó`   € \        V 4      P                  4       P                  R 4      R ,           # )Ú.)r2   ÚstripÚrstrip)r0   s   &r   r+   r+   6   s#   € Üˆt‹9�?‰?Ó×#Ñ# CÓ(¨3Õ.Ð.r   c                óF   € V ^8„  d   QhR\         R\        \         ,          /# ©r   Úprovider_idr   ©r2   r   )r   s   "r   r   r   :   s   € ÷  7ñ  7¤sð  7¬x¼­}ñ  7r   c           
     ó6  € ^ RI HpHpHp ^ RIHp . p\        P                  ! \        4      ;_uu_ 4        V! V 4       Uu. uF,  p\        V\        4      '       g   K  VP                  W4      NK.  	  ppRRR4       V Uu. uF  qfP                  V8w  g   K  VNK  	  ppV'       g   R# \        P                  ! 4       pV UU	u. uF)  pV! V\        V4      ^8H  R7      p	V	f   K  W˜8”  g   K'  V	NK+  	  p
pp	\        V
4      \        V4      8w  d   R# \        \         P"                  ! \%        V
4      4      P'                  4       R4      p\        V4      ^8X  d   RMR\        V4       R2pR	V  R
V RV RV  R2	# u upi   + '       g   i     EL; iu upi u up	pi )uk  The "all N credentials â€¦ are cooling down" error when the provider's pool is fully benched.

``resolve_provider_client()`` returns ``None`` both when no credential exists and when every
pool entry sits in a 429/quota cooldown, so the raise sites could only say "no credentials
were found. Run hermes auth add â€¦" â€” wrong on both counts for a valid OAuth grant that is
merely rate-limited (#56810). Read the persisted pool state (no seeding, no writes) and name
the cooldown and its reset time instead; ``None`` when the pool is empty or a credential is
usable (the caller keeps the missing-credential diagnostic).
)ÚSTATUS_DEADÚPooledCredentialÚ_exhausted_until©Úread_credential_poolN©Úsole_credentialz%Y-%m-%d %H:%M %Zúits only credential isúall ú credentials areú
Provider 'ú' is set in config.yaml but zM cooling down after a rate limit / quota error (429); the next one resets at zC. Wait for the reset, add another credential with `hermes auth add z9`, or switch to a different provider with `hermes model`.)Úagent.credential_poolr<   r=   r>   r%   r@   r'   r(   r)   r,   ÚdictÚ	from_dictÚlast_statusÚtimeÚlenr   r   ÚfromtimestampÚminÚ
astimezone)r9   r<   r=   r>   r@   ÚentriesÚeÚliveÚnowÚuntilÚresetsÚwhenÚwhichs   &            r   Úpool_cooldown_messagerY   :   s†  € ÷ VÑUÝ4à€GÜ	×	Ò	œY×	'Õ	'á0°Ô=óVÙ=�qÄÈAÌt×ATô >Ð#×-Ñ-¨kÖ=Ù=ð 	ð V÷ 
(ñ Ó?‘w�!§-¡-°;Ñ">�AˆA‘w€DÐ?ßÙÜ
�)Š)‹+€CÙ!ô 4™T˜Ù,¨QÄÀDÃ	ÈQÁÔO�%Øô à',¡{÷ ˆe™T€Fñ 4ô ˆ6ƒ{”c˜$“iÔÙÜœ×/Ò/´°F³Ó<×GÑGÓIÐK^Ó_€DÜ),¨T«°a¬Ñ%Øœ˜T›˜Ð#3Ð4ð 
à˜˜Ð%AÀ%Àð IFØFJÀVð L<Ø<G¸=ð I6ð6ð 7ùòV÷ 
(×	'Ð	'üò @ùó4sA   µE<Á E7ÁE7Á2E<Â FÂFÃFÃ$FÃ,FÅ7E<Å<F	c                   óJ   a a€ ] tR t^]t oRtRR/V3R lV 3R llltRtVtV ;t# )Ú!ProviderCredentialsExhaustedErrorax  An explicit provider's credential pool is fully exhausted (402 out of credits, quota bench).

Subclasses ``RuntimeError`` so every existing ``except RuntimeError`` keeps working; the distinct
type lets a caller (gateway, Desktop) route a billing/quota failure to billing guidance instead
of the provider-setup flow a plain "No LLM provider configured" would trigger (#94785).
r!   Nc                ó6   <€ V ^8„  d   QhRS[ RS[S[ ,          /# )r   r   r!   r:   )r   Ú__classdict__s   "€r   r   Ú.ProviderCredentialsExhaustedError.__annotate__e   s   ø€ ÷ !ñ !¡ð !±(¹3µ-ñ !r   c               ó2   <€ \         SV `  V4       W n        R # ©N)ÚsuperÚ__init__r!   )Úselfr   r!   Ú	__class__s   &&$€r   rb   Ú*ProviderCredentialsExhaustedError.__init__e   s   ø€ Ü‰Ñ˜Ô!Ø Žr   )r!   )	r
   r   r   r   r   rb   r   Ú__classdictcell__Ú__classcell__)rd   r]   s   @@r   r[   r[   ]   s    ù‡ € ñð!À$÷ !÷ !õ !r   r[   ÚmodelÚpoolc          	      óŠ   € V ^8„  d   QhR\         R\        \         ,          R\        \        ,          R\        \         ,          /# )r   r9   rh   ri   r   )r2   r   r   )r   s   "r   r   r   j   sD   € ÷ Gñ GÜðGô ”C�=ðGô ”3�-ð	Gô
 Œc…]ñGr   c          	     ó²  € ^ RI HpHpHpHpHp . p\        P                  ! \        4      ;_uu_ 4        Ve   \        VP                  4       4      pMD^ RIHp	 V	! V 4       U
u. uF,  p
\        V
\        4      '       g   K  VP                  W
4      NK.  	  pp
RRR4       V U
u. uF  p
\!        V
RR4      V8w  g   K  V
NK  	  pp
V'       g   R# \"        P"                  ! 4       pV U
u. uF@  p
\!        V
RR4      V8X  g   K  V! V
\%        V4      ^8H  R7      ;'       g    ^ V8”  g   K>  V
NKB  	  pp
\%        V4      \%        V4      8w  d   R# V U
u. uF+  p
\!        V
RR4      R8X  g   \!        V
RR4      V8X  g   K)  V
NK-  	  pp
V'       g   R# V^ ,          p\!        VRR4      p\'        \!        VR	R4      ;'       g    R
4      P)                  4       p\%        V4      ^8X  d   RMR\%        V4       R2pV'       d   RV R2MR
pV'       d   RT V'       d
   RV,           MR
 R2MR
pRV  RV RV RV R2	# u up
i   + '       g   i     EL©; iu up
i u up
i u up
i )u-  The "Provider 'X' â€¦ is out of usable credentials (402)" error for a billing-burned pool.

``resolve_provider_client()`` returns ``None`` both when no credential exists and when every
pool entry has been marked exhausted â€” a 402 out-of-credits account, a 429/quota bench. The
``openrouter`` / ``custom`` branch of ``agent_init`` has no provider-specific missing-credentials
message, so a burned pool there fell through to the generic "No LLM provider configured" setup
message: actively misleading when a *different* provider is configured and working and only the
session's override is out of credits (#94785). Name the provider, the session's model, the last
error code and the provider's own message instead.

Only a genuine billing verdict â€” a 402, or the classifier's ``billing`` reason on a 403 spending
limit â€” is named here; a plain 429/quota bench keeps the existing cooldown wording (with its
reset time, #56810), which the caller falls back to when this returns ``None``.

*pool* is an already-loaded ``CredentialPool`` (preferred â€” it carries the live in-memory
exhaustion state); otherwise the persisted rows are read (no seeding, no writes, mirroring
``pool_cooldown_message``). ``None`` when the pool is empty, a credential is usable, no entry is
currently benched, or none carries a billing verdict.
)ÚFAILURE_REASON_BILLINGr<   ÚSTATUS_EXHAUSTEDr=   r>   Nr?   rK   rA   Úlast_error_codei’  Úfailure_reasonÚlast_error_messageÚ rC   rD   rE   z for model 'Ú'z (last error z: Ú)rF   z is out of usable credentials: z
 exhaustedzv. Add credits or update billing with that provider, then retry, or switch to a different provider with `hermes model`.)rH   rl   r<   rm   r=   r>   r'   r(   r)   ÚlistrQ   r%   r@   r,   rI   rJ   ÚgetattrrL   rM   r2   r5   )r9   rh   ri   rl   r<   rm   r=   r>   rQ   r@   rR   rS   rT   ÚbenchedÚbillingÚpickr    ÚdetailrX   ÚscopeÚ	code_texts   &$$                  r   Úpool_billing_messager|   j   sR  € ÷2õ ð €GÜ	×	Ò	œY×	'Õ	'ØÒÜ˜4Ÿ<™<›>Ó*‰Gå<ñ !5°[Ô AóZÙ A˜1ÄZÐPQÔSW×EXô BÐ'×1Ñ1°+ÖAÙ Að ð Z÷ 
(ñ ÓQ‘w�!¤'¨!¨]¸DÓ"AÀ[Ñ"P�AˆA‘w€DÐQßÙÜ
�)Š)‹+€CáóÙˆaÜ�1�m TÓ*Ð.>Ñ>ô 	
á˜a´°T³¸a±Ô@×EÐEÀAÈÑL÷ 	
ˆ‘4ð ð ô
 ˆ7ƒ|”s˜4“yÔ ááóÙˆaÜ�1Ð'¨Ó.°#Ô5Ü�1Ð&¨Ó-Ð1GÑG÷ 	
ˆ‘7ð ð ÷
 ÙØ�1�:€DÜ�4Ð*¨DÓ1€DÜ”˜Ð3°TÓ:×@Ð@¸bÓA×GÑGÓI€FÜ(+¨D«	°Q¬Ñ$¸dÄ3ÀtÃ9À+ÐM]Ð<^€Eß',ˆl˜5˜' Ñ#°"€EßLP�- ˜v·v d¨V¦mÀ2Ð%FÀaÑHÐVX€Ià
�[�M  5 'Ð)HÈÈÈzØˆ+ð 7ð	8ðùò7Z÷ 
(×	'Ð	'üò RùòùòsS   ³/H6Á"H1Á?H1ÂH6Â"I
Â;I
Ã&IÃ?IÄIÄ&IÅ&IÅ8IÈ1H6È6I	c                   ó   € ] tR t^´tRtRtR# )ÚProviderNotConfiguredErroraÑ  Agent init found no usable inference provider: nothing is configured, or the explicitly
configured one has no credentials.

A distinct type because the remedy is setup, not a retry: clients route it to their provider
setup / onboarding flow. The wording of the two messages has changed more than once, so a
client that recognises this failure by matching their text silently stops routing (#119232's
sibling); the type and the gateway's ``code`` survive rewording.
r   Nr	   r   r   r   r~   r~   ´   s   † õr   r~   c                ó0   € V ^8„  d   QhR\         R\         /# r8   )r2   )r   s   "r   r   r   ¿   s   € ÷ Mñ M´cð M¼cñ Mr   c                ó�  € \        V 4      pV'       d   V# Rp\        P                  ! \        4      ;_uu_ 4        ^ RIHp VP                  V 4      pRRR4       \        \        VRR4      ;'       g    R4      pRRre^ RI	H
p W9   d   RRreMsV'       d   R	V^ ,           R
2pM]Vf&   R	V P                  4       P                  RR4       R2pM4\        VP                  4      P                  R4      '       d	   RRV  R2reMRpRpRV  RV R2V'       d   V RV 2,           # VP!                  4       ,           #   + '       g   i     Lë; i)u.  The "Provider 'X' is set in config.yaml but â€¦" error for an explicit provider with no credentials.

The remedy comes from the registry, never from the provider id: ``f"{id.upper()}_API_KEY"``
invents names nothing reads (alibaba â†’ ALIBABA_API_KEY instead of DASHSCOPE_API_KEY, and the
unsettable MINIMAX-OAUTH_API_KEY for OAuth ids, #114405 / #78996). OAuth providers have no key
env var at all, so they are pointed at the sign-in command instead. A pool whose every
credential is cooling down is not "missing" â€” that case names the cooldown (#56810).
N)ÚPROVIDER_REGISTRYÚapi_key_env_varszno API key was foundrq   )ÚLLAMACPP_ALIASESz$no local llama.cpp server is runningu3   Start it in Settings â†’ Providers â†’ Local modelszSet the z environment variableÚ-Ú_z_API_KEY environment variableÚoauthzno credentials were foundzRun `hermes auth add z` to sign inz3switch to a different provider with `hermes model`.rF   rG   z. z, or r   )rY   r'   r(   r)   r%   r�   r*   Útupleru   Ú!hermes_cli.local_runtime.endpointrƒ   ÚupperÚreplacer2   Ú	auth_typeÚ
startswithÚ
capitalize)	r9   ÚcooldownÚpconfigr�   Úenv_varsÚproblemÚremedyrƒ   Úswitchs	   &        r   Ú$missing_provider_credentials_messager”   ¿   sC  € ô % [Ó1€HßØˆØ€GÜ	×	Ò	œY×	'Õ	'Ý5Ø#×'Ñ'¨Ó4ˆ÷ 
(ô ”W˜WÐ&8¸$Ó?×EÐEÀ2ÓF€HØ,¨bˆVÝBØÔ&Ø@ÐBw‘ß	Ø˜H Q�K˜=Ð(=Ð>‰Ø	ŠØ˜K×-Ñ-Ó/×7Ñ7¸¸SÓAÐBÐB_Ð`‰Ü	ˆW×ÑÓ	×	*Ñ	*¨7×	3Ò	3Ø5Ð9NÈ{ÈmÐ[gÐ7h‘à-ˆØB€FØ˜˜Ð%AÀ'ÀÈ"ÐMß+1�&�˜˜v˜hÐ'õLð MØ7=×7HÑ7HÓ7JõLð M÷# 
(×	'ús   ºD5Ä5E	c                ó0   € V ^8„  d   QhR\         R\        /# r   )r   Úbool)r   s   "r   r   r   á   s   € ÷ ñ ¤-ð ´Dñ r   c                óÜ   € \        V RR4      '       d   R# ^ RIHp \        P                  ! \
        4      ;_uu_ 4        \        V! R4      4      uuRRR4       #   + '       g   i     R# ; i)u„  True when a Nous credential exists that failed â€” a coded error (``invalid_grant``, a quarantine
marker, ``refresh_failed``) or persisted Nous auth state. The uncoded "not logged into Nous Portal"
with no stored state is the normal condition for users who never chose Nous; the auto-route walk
hits it on every discovery pass and must not warn (the ladder already logs its own summary).
r    NT)r   r   F)ru   r%   r   r'   r(   r)   r–   )r   r   s   & r   Ú_nous_credential_presentr˜   á   sJ   € ô ˆs�F˜D×!Ò!ÙÝ7ä	×	Ò	œY×	'Õ	'ÜÑ+¨FÓ3Ó4÷ 
(×	'×	'Ñ	'áús   ¾AÁA+	c                ó0   € V ^8„  d   QhR\         R\        /# r   )r   r2   )r   s   "r   r   r   ð   s   € ÷ ñ ¬ð ¼#ñ r   c                ól  € ^ RI Hp \        V 4      p \        V \        4      '       d	   V! V 4      M
\        V 4      pVP                  4       ;'       g    \        V 4      P                  p\        V RR4      pV'       d   \        V4      V9  d	   V RV R2pRV 2p\        ;_uu_ 4        VsV\        9  p\        P                  V4       RRR4       X'       dI   \        V 4      '       d   \        P                   M\        P"                  p\$        P'                  VRV4       V#   + '       g   i     Lb; i)zµRemember *exc* as the latest Nous credential failure.

Logged once per distinct message: WARNING when a real credential failed, DEBUG when Hermes was
simply never logged into Nous.
)Úformat_auth_errorr    Nz (code: rs   z-Nous Portal runtime credentials unavailable: z%Auxiliary Nous client unavailable: %s)r%   r›   r.   r,   r)   r2   r5   Útyper
   ru   Ú_lockÚ_last_nous_detailÚ_warned_nous_detailsÚaddr˜   ÚloggingÚWARNINGÚDEBUGÚloggerÚlog)r   r›   r   r    ry   Ú
first_timeÚlevels   &      r   Úrecord_nous_credential_failurer¨   ð   sê   € õ 2ä
! #Ó
&€CÜ(2°3¼	×(BÒ(BÑ Ô$ÌÈCË€GØ�m‰m‹o×3Ð3¤ c£×!3Ñ!3€GÜ�3˜ Ó%€Dß”�D“	 Ô(Ø�I˜X d V¨1Ð-ˆØ<¸W¸IÐF€Fç	ŽØ"ÐØÔ#7Ñ7ˆ
Ü× Ñ  Ô(÷ 
÷ Ü#;¸C×#@Ò#@”—’ÄgÇmÁmˆÜ�
‰
�5ÐAÀ6ÔJØ€M÷ 
�ús   Â(!D#Ä#D3	c                ó   € V ^8„  d   QhRR/# )r   r   Nr   )r   s   "r   r   r   
  s   € ÷ !ñ ! tñ !r   c                  ó`   € \         ;_uu_ 4        R sR R R 4       R #   + '       g   i     R # ; ir`   ©r�   rž   r   r   r   Úclear_nous_credential_failurer¬   
  s   € ç	ŽØ Ð÷ 
��Šús   �œ-	c                ó:   € V ^8„  d   QhR\         \        ,          /# )r   r   )r   r2   )r   s   "r   r   r     s   € ÷ !ñ !¬´­ñ !r   c                 óh   € \         ;_uu_ 4        \        uuRRR4       #   + '       g   i     R# ; i)zXThe latest recorded Nous credential failure, or None when the last resolution succeeded.Nr«   r   r   r   Únous_credential_failure_detailr¯     s   € ç	ŽÜ ÷ 
��‹ús   �  1	c                ó”   € V ^8„  d   Qh/ ^ \         9   d   \        \        ,          ;R&   ^\         9   d   \        \        ,          ;R&   # )r   rž   rŸ   )Ú__conditional_annotations__r   r2   Úset)r   s   "r   r   r      s8   € ÷ ñ ÷4 (Ò '”8œC•=Ñ 'ñ5÷6 'Ò &”cœ#•hÑ &ò7r   )"r±   r   r'   r¡   Ú	threadingrL   r   Útypingr   r   Úhermes_timer   Ú	getLoggerr
   r¤   ÚRuntimeErrorr   ÚLockr�   rž   r²   rŸ   r.   r+   rY   r[   r|   r~   r”   r˜   r¨   r¬   r¯   r   )r±   s   @r   Ú<module>r¹      sÂ   øðöó Û Û Û Ý ß  å %à	×	Ò	˜8Ó	$€ô\ ô \ð 	�ŠÓ€Ø#'Ð Ó 'Ù!$£Ð Ó &õõ./õ 7ôF
!¨ô 
!ðGð  ðGð ÷	GôT ô õMõDõõ4!÷!r   