+
    „WÝjKï  ã                  ó‚  a € 0 t $ R t^ RIHt ^ RIt^ RIt^ RIt^ RIt^ RIH	t	 ^ RI
H
t
HtHtHt ^ RIHt ^ RIHtHtHtHt ^ RIHt ^ RIHtHtHtHtHtHtHt ]P>                  ! R	4      t R
t!Rt"R
t#Rt$Rt%Rt&Rt'Rt(Rt)Rt*Rt+ ! R R]4      t,RR/R R llt-Rt.Rt/Rt0Rt1Rt2Rt3Rt4R t5R!t6R"t7]8! ].]1]2]704      t9]8! ]4]504      t:R#t;].R$]; 2]/R%]; 2]0R&]1R']6R(]7R)]2R*]; 2]3R+]4R,]5R-/
t<R. R/ lt=RR/R0 R1 llt>R2 R3 lt?R4 R5 lt@R6 R7 ltAR8 R9 ltBR: R; ltCR< R= ltDR> R? ltERÆR@ RA lltFRB RC ltGRD RE ltHRF RG ltIRH RI ltJ]8! RJ04      tKRKtLRL RM ltMRN RO ltNRP RQ ltORR RS ltPRT RU ltQRV RW ltRRX RY ltSRÇ],]33RÈ]].3RÉ]].3RÊ],]33RË],]23RÌ]]/3RÍ]]/3RÎ]]13RÏ]]03RÐ]]/3/
tTRZ]UR[&   ]]V]W]3,          .]3,          tXR\R/R] R^ lltYR_ R` ltZRa Rb lt[Rc Rd lt\ReR/Rf Rg llt]Rh Ri lt^Rj Rk lt_Rl Rm lt`Rn Ro ltaRp Rq ltbRÑtcRrtd]	 ! Rs Rt4      4       te/ tfRu]URv&   Rw Rx ltgRy Rz lthR{ R| ltiR} R~ ltjR R€ ltkR� R‚ ltlRƒ R„ ltmR…R†R‡R†/Rˆ R‰ lltnRŠ](R…R†R‡R†/R‹ RŒ lltoR� RŽ ltpR�R/R� R‘ lltqR’tr]8! 0 RÒm4      ts]8! R“R”04      ttRÓtuR•R™R–RšR—R›R˜Rœ/tvR�twRžtxRŸtyR tzR¡t{R¢ R£ lt|R¤R¥R¦R§R¨R§/R© Rª llt}RÆR« R¬ llt~R¦R§R¨R§/R­ R® lltR¯ R° lt€R± R² lt�R³t‚R´ Rµ ltƒR¶ R· lt„R¸ R¹ lt…Rº R» lt†R¼t‡R½ R¾ ltˆR¿ RÀ lt‰RÁ RÂ ltŠRÃ t‹^ RÄIŒH�t�HŽtŽH�t�H�t�H‘t‘H’t’H“t“H”t”H•t•H–t–H—t—H˜t˜H™t™HštšH›t›HœtœH�t�HžtžHŸtŸH t H¡t¡H¢t¢H£t£H¤t¤H¥t¥H¦t¦H§t§H¨t¨ ^ RÅI©HªtªH«t«H¬t¬H­t­ R# )Ôu�  Nous free-tier identity: the ``anonymous`` auth method of the ``nous`` provider.

The identity is created in two places: by the desktop's first install, which claims the welcome
trial (``hermes_cli.welcome_trial``), and on the first hosted connector action for anyone without a
Nous identity (``tools.connectors.gateway.config.ensure_guest_identity``, gated by ``guest_allowed``).
Either mints an anonymous Nous account (``POST /api/anonymous/create``); its ``anon_`` credential is
later exchanged for short-lived JWTs (``POST /api/anonymous/token``). The result is persisted as the
singleton ``providers.nous``. Only a guest stamped with the trial claim carries inference
(:func:`free_inference_active`), on every surface of the install once the desktop claimed it: chats,
cron, side agents, workers, the CLI. Every other guest serves connectors and managed tools. In the resolver ladder (``resolve_provider``) a guest that
carries inference sits directly above the implicit AWS Bedrock chain (NS-829): any explicit provider
(env key, ``model.provider``, OpenRouter pool, a logged-in ``active_provider``) beats it, and the
ladder never creates one.

Only two mechanics differ from an OAuth login and both are isolated behind ``is_guest_state``:
token acquisition (re-exchange the ``anon_`` credential; there is no refresh token) and routing
(the welcome inference host, single model ``nous/welcome``).

Users are never shown the words guest / anonymous / account for this state: surfaces say
"Nous Â· free tier". Two user-facing verbs reach the same flow, both keeping the identity's
connectors: ``hermes auth upgrade`` in a terminal and ``/login`` inside a chat.

Lifecycle lives in ONE primitive, :func:`_reconcile_and_provision`: adopt what the shared store already
holds, else mint under the shared-store lock. :func:`ensure_portal_identity` (connectors) and the
welcome-trial claim are its only callers; nothing else calls :func:`mint_guest`.
)ÚannotationsN)Ú	dataclass)ÚdatetimeÚ	timedeltaÚtimezoneÚUTC)ÚPath)ÚAnyÚCallableÚDictÚOptional)Úparse_retry_after_seconds)Ú	AuthErrorÚDEFAULT_NOUS_PORTAL_URLÚDEFAULT_NOUS_WELCOME_URLÚNOUS_INFERENCE_INVOKE_SCOPEÚWELCOME_CLAIM_FLAGÚ_decode_jwt_claimsÚhttpxzhermes_cli.authÚ	anonymousznas-anonymousznous/welcomezx-anonymous-api-secretÚHERMES_ANON_API_SECRETÚHERMES_PREVIEW_FULL_CONNECTORSç      @u   Nous Â· free tierzRRun `hermes auth upgrade` to sign in with a Nous account, or /login inside a chat.ztYou're not signed in. Free inference and connectors are always on. Run `hermes auth` to sign in with a Nous account.c                  ó   € ] tR t^DtRtRtR# )ÚAnonCredentialDeadz¦NAS no longer knows this ``anon_`` credential (reaped, or claimed into a real account).

The one client rule for reap AND claim: mark dead, re-mint on the next need.
© N)Ú__name__Ú
__module__Ú__qualname__Ú__firstlineno__Ú__doc__Ú__static_attributes__r   ó    ÚHC:\Users\johnn\AppData\Local\hermes\hermes-agent\hermes_cli\anon_auth.pyr   r   D   s   † õr"   r   Úretry_afterc               ó(   € V ^8„  d   QhRRRRRRRR/# )é   ÚmessageÚstrÚcoder$   zOptional[float]Úreturnr   r   )Úformats   "r#   Ú__annotate__r,   K   s/   € ÷ mñ m�sð m #ð m°ð mÐR[ñ mr"   c               ó*   € \        WW!\        9  R7      # )zgAn ``AuthError`` for a free-tier failure *code*; terminal-ness is the code's (``ANON_TERMINAL_CODES``).©r)   r$   Ú	retryable)r   ÚANON_TERMINAL_CODES)r'   r)   r$   s   &&$r#   Ú	_anon_errr1   K   s   € ä�W°[ÔXkÑLkÔlÐlr"   Úanon_gate_closedÚanon_gate_pausedÚanon_rate_limitedÚanon_pow_requiredÚanon_account_lockedÚanon_credential_deadÚanon_unreachableÚanon_server_errorÚanon_challenge_requiredÚanon_signin_requiredzSigning in is free.z3This version can't be used without a Nous account. z8Using Hermes without signing in is paused for a moment. ziLots of people are getting started right now. Try again in {wait}. Signing in is free and skips the wait.z�The Nous server asked for a proof of work, but that isn't implemented in your Agent yet. Sign in with a Nous account to continue.z7Finish the quick check in your browser, then try again.zPFree guest access isn't available here. Sign in with a Nous account to continue.z0This session can't continue without signing in. z0Your session ended. A new one starts on its own.zSThe Nous service couldn't be reached. Check your internet connection and try again.z5The Nous service had a hiccup. Try again in a moment.c               ó    € V ^8„  d   QhRRRR/# )r&   Úsecondsr	   r*   r(   r   )r+   s   "r#   r,   r,   …   s   € ÷ Eñ E˜3ð E 3ñ Er"   c                ó  €  \        R\        T ;'       g    ^ 4      4      pV^8:  d   R# V^Z8  d   R# VR8  d   R\	        V^<,          4       R2# \	        VR,          4      pV^8:  d   R# RV R2#   \        \        3 d    Rp Lei ; i)	zŠA rounded, spoken duration for user copy: "a few seconds", "about a minute", "about 5 minutes",
"about an hour". Never a raw second count.ç        za few secondszabout a minutei  zabout z minuteszabout an hourz hours)ÚmaxÚfloatÚ	TypeErrorÚ
ValueErrorÚround)r=   ÚsÚhourss   &  r#   Úfriendly_waitrG   …   s”   € ðÜ�”U˜7Ÿ<˜< aÓ(Ó)ˆð 	ˆB„wÙØˆ2„vÙØˆ4„xØœ˜a "�f›� hÐ/Ð/Ü�!�d•(‹O€EØ# qœjˆ?ÐD°°u°g¸VÐ.DÐDøô ”zÐ"ô ØŠðús   ‚A1 –A1 Á1BÂBc               ó$   € V ^8„  d   QhRRRRRR/# )r&   r)   r(   r$   r	   r*   r   )r+   s   "r#   r,   r,   –   s&   € ÷ Sñ S˜Cð S°ð SÀñ Sr"   c               óº   € \         P                  V 4      ;'       g    \         \        ,          pTP                  \	        V'       d   V4      R7      # ^<4      R7      # )zUThe surface-agnostic sentence for a free-tier failure *code* (``ANON_FAILURE_COPY``).)Úwait)ÚANON_FAILURE_COPYÚgetÚANON_SERVER_ERRORr+   rG   )r)   r$   Útemplates   &$ r#   Úanon_failure_copyrO   –   sF   € ä ×$Ñ$ TÓ*×RÐRÔ.?Ô@QÕ.R€HØ�?‰?¤¿[¨kÓ Qˆ?ÓRÐRÈbÓ Qˆ?ÓRÐRr"   c               ó   € V ^8„  d   QhRR/# ©r&   r*   Úboolr   )r+   s   "r#   r,   r,   œ   s   € ÷ 
-ñ 
-�tñ 
-r"   c                 óô   €  ^ RI Hp  V ! 4       P                  R4      p\        T\        4      '       g   R# \        TP                  RR4      4      #   \         d    \        P                  RRR7        R# i ; i)zX``nous.guest`` (default True) has not switched guests off: no connector guest, no trial.©Úload_config_readonlyÚnousz6guest: config unreadable, treating nous.guest as falseT)Úexc_infoFÚguest)	Úhermes_cli.configrU   rL   Ú	ExceptionÚloggerÚdebugÚ
isinstanceÚdictrR   )rU   Únous_cfgs     r#   Úguest_allowedr`   œ   sk   € ðÝ:Ù'Ó)×-Ñ-¨fÓ5ˆô �h¤×%Ò%ÙÜ�—‘˜W dÓ+Ó,Ð,øô ô Ü�‰ÐMÐX\ˆÔ]Úðús   ‚A Á"A7Á6A7c               ó    € V ^8„  d   QhRRRR/# ©r&   Ústater	   r*   rR   r   )r+   s   "r#   r,   r,   ©   s   € ÷ Tñ T˜#ð T $ñ Tr"   c                ób   € \        V \        4      ;'       d    V P                  R 4      \        8H  # )Úauth_method)r]   r^   rL   ÚANON_AUTH_METHOD©rc   s   &r#   Úis_guest_staterh   ©   s&   € Ü�eœTÓ"×SÐS u§y¡y°Ó'?ÔCSÑ'SÐSr"   c               ó$   € V ^8„  d   QhRRRRRR/# )r&   Úproviderr	   Úapi_keyr*   rR   r   )r+   s   "r#   r,   r,   ­   s&   € ÷ gñ g 3ð g°ð g¸ñ gr"   c                ód   € ^ RI Hp V R8H  ;'       d    V! V4      P                  R4      \        8H  # )a  Select anonymous error UX from the credential actually sent, never the saved profile or URL.

This is display/recovery metadata, not token verification; the gateway authenticates the JWT.
Named free accounts and opaque API keys must retain normal provider errors.
)r   rV   Úaccount_tier)Úhermes_cli.auth_constantsr   rL   ÚANON_ACCOUNT_TIER)rj   rk   r   s   && r#   Úis_anonymous_requestrp   ­   s1   € õ =Ø�vÑ×fÐfÑ"4°WÓ"=×"AÑ"AÀ.Ó"QÔUfÑ"fÐfr"   c               ó    € V ^8„  d   QhRRRR/# )r&   Úagentr	   r*   rR   r   )r+   s   "r#   r,   r,   ·   s   € ÷ añ a˜cð a dñ ar"   c                óF   € \        \        V RR4      \        V RR4      4      # )z_:func:`is_anonymous_request` for a live agent: read at call time, since the credential rotates.rj   Ú rk   N)rp   Úgetattr)rr   s   &r#   Úis_anonymous_agentrv   ·   s"   € ä¤¨¨z¸2Ó >ÄÈÈyÐZ^Ó@_Ó`Ð`r"   c               ó   € V ^8„  d   QhRR/# ©r&   r*   úOptional[dict[str, Any]]r   )r+   s   "r#   r,   r,   ¼   s   € ÷ ñ Ð4ñ r"   c                 óŽ   € ^ RI Hp Hp  V! V ! 4       R4      #   \         d"   p\        P                  RT4        Rp?R# Rp?ii ; i)zXThe profile's ``providers.nous`` state without locking or network (status/picker reads).)Ú_load_auth_storeÚ_load_provider_staterV   z guest: auth store unreadable: %sN)Úhermes_cli.authr{   r|   rZ   r[   r\   )r{   r|   Úexcs      r#   Úcurrent_nous_stater   ¼   s=   € çFðÙ#Ñ$4Ó$6¸Ó?Ð?øÜô Ü�‰Ð7¸Ô=Ýûðús   Š ˜A£?¿Ac               ó   € V ^8„  d   QhRR/# rQ   r   )r+   s   "r#   r,   r,   Æ   s   € ÷ 0ñ 0�4ñ 0r"   c                 ó(   € \        \        4       4      # ©N)rh   r   r   r"   r#   Ú	has_guestrƒ   Æ   s   € ÜÔ,Ó.Ó/Ð/r"   c               ó   € V ^8„  d   QhRR/# rQ   r   )r+   s   "r#   r,   r,   Ê   s   € ÷ &ñ & $ñ &r"   c                 ó   € ^ RI Hp  V ! 4       # )a  This activity is work for the Desktop app on this machine: a request from, or a turn of a chat
created by, a connection ``process_identity.local_desktop_client`` accepted. Never an SSH, URL or
cloud backend, a shell the desktop launched, or the gateway's other clients.©Úserves_local_desktop_now)Úhermes_cli.process_identityr‡   r†   s    r#   Úon_local_desktop_backendr‰   Ê   s   € õ EÙ#Ó%Ð%r"   c               ó    € V ^8„  d   QhRRRR/# rb   r   )r+   s   "r#   r,   r,   Ò   s   € ÷ _ñ _ ð _°ñ _r"   c                óš   € V f   \        4       MT p \        V 4      ;'       d*    V P                  \        4      RJ ;'       d    \	        4       # )zëThe welcome trial carries inference: a guest that claimed it and guests
still allowed. Only the claim is the local Desktop's (``welcome_trial``); once claimed, every
surface of the install runs on it. *state* defaults to the profile's.T)r   rh   rL   r   r`   rg   s   &r#   Úfree_inference_activerŒ   Ò   s?   € ð %*¢MÔÔ °u€EÜ˜%Ó ×^Ð^ U§Y¡YÔ/AÓ%BÀdÐ%J×^Ð^Ì}ËÐ^r"   c               ó   € V ^8„  d   QhRR/# ©r&   r*   r(   r   )r+   s   "r#   r,   r,   Ú   s   € ÷ :ñ :�Sñ :r"   c                 ó2   € \        4       '       d   \        # R# )a  The last rung of model resolution, below every model the user named (``model.default``, a cron
or task pin): ``nous/welcome`` while the welcome trial carries inference, else ''. Never written to
config.yaml, so it stops applying the moment the user configures a real model.rt   )rŒ   ÚGUEST_MODELr   r"   r#   Útrial_modelr‘   Ú   s   € ô 0×1Ò1Œ;Ð9°rÐ9r"   c               ó   € V ^8„  d   QhRR/# rQ   r   )r+   s   "r#   r,   r,   á   s   € ÷ #ñ #˜tñ #r"   c                 ó   € \        4       # )ae  True when the profile's Nous identity is a guest that carries inference here.

Profile-level: use for status, picker and notice surfaces. Routing decisions (which model a
request may carry) must use :func:`route_is_welcome_host` on the SELECTED runtime instead: a
credential-pool entry can pick a paid Nous key while the profile singleton is still a guest.
)rŒ   r   r"   r#   Úhas_free_tier_accountr”   á   s   € ô !Ó"Ð"r"   c               ó    € V ^8„  d   QhRRRR/# rb   r   )r+   s   "r#   r,   r,   ë   s   € ÷ Fñ F 3ð F¨4ñ Fr"   c                óH   € \        V 4      ;'       d    \        V 4      '       * # )z¥A guest that does not carry inference here: it serves connectors and managed tools only, so
inference, account and status readers treat the profile as not signed in.)rh   rŒ   rg   s   &r#   Úguest_without_free_tierr—   ë   s    € ô ˜%Ó ×EÐEÔ)>¸uÓ)EÔ%EÐEr"   c               ó   € V ^8„  d   QhRR/# rQ   r   )r+   s   "r#   r,   r,   ñ   s   € ÷ Jñ J˜ñ Jr"   c                 óH   € ^ RI Hp  \        4       ;'       d    V ! R4      R8H  # )é    ©Úresolve_providerÚautorV   )r}   rœ   r”   r›   s    r#   Úfree_tier_routerž   ñ   s!   € Ý0Ü Ó"×IÐIÑ'7¸Ó'?À6Ñ'IÐIr"   zwelcome-api.nousresearch.comÚHERMES_EXTRA_WELCOME_HOSTSc               ó   € V ^8„  d   QhRR/# )r&   r*   zfrozenset[str]r   )r+   s   "r#   r,   r,   þ   s   € ÷ Hñ H�~ñ Hr"   c                 óT  € \         P                  P                  \        4      ;'       g    Rp V P	                  R4       Uu0 uF8  qP                  4       '       g   K  VP                  4       P                  4       kK:  	  ppV'       d   \        \        V4      ,          # \        # u upi )zY``WELCOME_HOSTS`` plus any ``HERMES_EXTRA_WELCOME_HOSTS`` entries (lowercased hostnames).rt   Ú,)	ÚosÚenvironrL   ÚEXTRA_WELCOME_HOSTS_ENVÚsplitÚstripÚlowerÚWELCOME_HOSTSÚ	frozenset)ÚrawÚpartÚextras      r#   Úwelcome_hostsr®   þ   sn   € ä
�*‰*�.‰.Ô0Ó
1×
7Ð
7°R€CØ.1¯i©i¸¬nÓM©n dÇ
Á
ÇÔ!ˆT�Z‰Z‹\×ÑÖ!©n€EÐMß/4Œ=œ9 UÓ+Õ+ÐG¼-ÐGùò Ns   ÁB%Á"B%c               ó(   € V ^8„  d   QhRRRRRRRR/# )r&   rj   r	   Úbase_urlÚmodelr*   r   )r+   s   "r#   r,   r,     s(   € ÷ 
ñ 
 #ð 
°ð 
¸Sð 
ÀSñ 
r"   c                óž   € V R8X  dF   \        V4      '       d5   V'       d'   V\        8w  d   \        P                  R\        V4       \        # V# )aJ  Model policy at agent START: on the Nous welcome host the model is ``nous/welcome``; anywhere
else the caller's model stands. Used once, when the route is first finalized. Mid-conversation
route changes go through :func:`route_can_serve_model` instead: a conversation's model is never
silently rewritten by a credential rotation.
rV   z7Nous free tier: using %s instead of configured model %s)Úroute_is_welcome_hostr�   r[   Úinfo©rj   r°   r±   s   &&&r#   Úpin_model_for_router¶     s?   € ð �6ÔÔ3°H×=Ò=ß�UœkÔ)Ü�K‰KÐQÔS^Ð`eÔfÜÐØ€Lr"   c               ó(   € V ^8„  d   QhRRRRRRRR/# )r&   rj   r	   r°   r±   r*   rR   r   )r+   s   "r#   r,   r,     s(   € ÷ -ñ - Cð -°3ð -¸sð -Àtñ -r"   c                óf   € V R8w  g   \        V4      '       g   R# V'       * ;'       g
    V\        8H  # )a  Eligibility for a credential ROTATION: the welcome host serves only ``nous/welcome``, so a
conversation on any other model must not be rotated onto it (and a ``nous/welcome`` conversation
may move to the portal host, which serves it too). Non-Nous routes are always eligible.rV   T)r³   r�   rµ   s   &&&r#   Úroute_can_serve_modelr¹     s/   € ð �6ÔÔ!6°x×!@Ò!@ÙØŒ9×,Ð,˜¤Ñ,Ð,r"   c               ó    € V ^8„  d   QhRRRR/# )r&   r°   r	   r*   rR   r   )r+   s   "r#   r,   r,     s   € ÷ #ñ # Cð #¨Dñ #r"   c                óÈ   € ^ RI Hp  T! \        T ;'       g    R4      4      P                  ;'       g    RP	                  4       pT\        4       9   #   \
         d     R# i ; i)a  The routing predicate for the free tier: the welcome host serves exactly ``nous/welcome``.

Keyed on the resolved endpoint, never on profile state, so a paid pool credential routed to the
portal host keeps its model even when a guest singleton exists beside it.
)Úurlparsert   F)Úurllib.parser¼   r(   Úhostnamer¨   rC   r®   )r°   r¼   Úhosts   &  r#   r³   r³     s[   € õ &ðÙœ˜XŸ^˜^¨Ó,Ó-×6Ñ6×<Ð<¸"×CÑCÓEˆð ”=“?Ñ"Ð"øô ô Úðús   ˆA ˜A ´A ÁA!Á A!c               ó$   € V ^8„  d   QhRRRRRR/# )r&   rr   r	   r°   r*   rR   r   )r+   s   "r#   r,   r,   )  s&   € ÷ Iñ I˜ð I¨ð I°ñ Ir"   c                ó>   € \        V4      ;'       d    \        V 4      # )zCThe request went to the free tier's host on a free-tier credential.)r³   rv   )rr   r°   s   &&r#   Úon_free_modelrÂ   )  s   € ä  Ó*×HÐHÔ/AÀ%Ó/HÐHr"   c               ó   € V ^8„  d   QhRR/# rŽ   r   )r+   s   "r#   r,   r,   .  s   € ÷ ;ñ ;�Sñ ;r"   c                 óx   € \         P                  P                  \        4      ;'       g    R P	                  4       # )rt   )r£   r¤   rL   ÚANON_SECRET_ENVr§   r   r"   r#   Úanon_secretrÆ   .  s&   € Ü�J‰J�N‰Nœ?Ó+×1Ð1¨r×8Ñ8Ó:Ð:r"   c               ó   € V ^8„  d   QhRR/# )r&   r*   zdict[str, str]r   )r+   s   "r#   r,   r,   2  s   € ÷ ñ �~ñ r"   c                 ó\   € ^ RI Hp  RRRV ! 4       /p\        4       ;p'       d	   W!\        &   V# )rš   )Ú
user_agentzcontent-typezapplication/jsonz
user-agent)Úhermes_cli.anon_challengerÉ   rÆ   ÚANON_SECRET_HEADER)rÉ   ÚheadersÚsecrets      r#   Ú_anon_headersrÎ   2  s1   € Ý4ØÐ1°<ÁÃÐN€GÜ“Ð€vÖØ&,Ô"Ñ#Ø€Nr"   zdict[tuple, tuple]Ú_NAS_REFUSALSÚ	overridesc               ó(   € V ^8„  d   QhRRRRRRRR/# )	r&   Úresponsezhttpx.ResponseÚactionr(   rÐ   zOptional[dict[tuple, _Verdict]]r*   údict[str, Any]r   )r+   s   "r#   r,   r,   L  s,   € ÷ 9ñ 9Øð9Ø),ð9Ø9Xð9àñ9r"   c               ó&  €  V P                  4       p\        V\        4      '       g   / p\	        VP                  R 4      ;'       g    R4      pV P                  pVR9   d   V# VP                  R4      '       d   RpV'       d>   VP                  WT34      ;'       g    VP                  VR34      pV'       d	   V! V4      h\        P                  WT34      ;'       g?    \        P                  VR34      ;'       g     VR8X  d   \        \        3M\        \        3w  rxV\        8X  d%   \        P                  RYV'       d   RV 2MR4       \        V P                  4      p	V! \!        W‰R7      W‰V\"        9  R7      h  \         d    / p EL}i ; i)	Úerrorrt   Úpow_NzNous free tier %s failed (%s%s)z: ©r$   r.   )éÈ   éÉ   )ÚjsonrC   r]   r^   r(   rL   Ústatus_codeÚ
startswithrÏ   r   ÚANON_POW_REQUIREDrM   r[   r´   r   rÌ   rO   r0   )
rÒ   rÓ   rÐ   ÚpayloadrÖ   ÚstatusÚbuildÚclsr)   r$   s
   &$$       r#   Ú_raise_for_anon_statusrã   L  sh  € ðØ—-‘-“/ˆô �gœt×$Ò$ØˆÜ�—‘˜GÓ$×*Ð*¨Ó+€EØ×!Ñ!€FØ�ÔØˆØ×Ñ˜×ÒØˆçØ—‘˜v˜oÓ.×OÐO°)·-±-ÀÈÀÓ2OˆßÙ˜“.Ð Ü×"Ñ" F ?Ó3÷ lð l´}×7HÑ7HÈ&ÐRVÈÓ7X÷ lð lØ7<À´”iÔ!2Ñ3ÌYÔXiÐLjñ €CàÔ Ô Ü�‰Ð5°v×W\ÈÈEÈ7Á|ÐbdÔeÜ+¨H×,<Ñ,<Ó=€KÙ
Ô Ô>ÀTØÔ$7Ñ7ô9ð 9øô) ô Ø‹ðús   ‚E? Å?FÆFc               ó   € V ^8„  d   QhRR/# ©r&   r*   rÔ   r   )r+   s   "r#   r,   r,   i  s   € ÷ kñ k˜>ñ kr"   c                 ó˜   € \         P                  P                  \        4      ;'       g    RP	                  4       p V R9   d   RV R9   /# / # )z‘The ``/api/anonymous/create`` body: ``{"preview_full_connectors": bool}`` when the env var is
``1`` / ``true`` or ``0`` / ``false``, else ``{}``.rt   Úpreview_full_connectors)Ú1ÚtrueÚ0Úfalse)rè   ré   )r£   r¤   rL   ÚPREVIEW_FULL_CONNECTORS_ENVr§   )r«   s    r#   Úmint_request_bodyrí   i  sG   € ô �:‰:�>‰>Ô5Ó6×<Ð<¸"×
CÑ
CÓ
E€CØ@CÐGbÔ@bÐ% s¨mÑ';Ð<ÐjÐhjÐjr"   c               ó$   € V ^8„  d   QhRRRRRR/# )r&   Úclientúhttpx.ClientÚportal_base_urlr(   r*   rÔ   r   )r+   s   "r#   r,   r,   p  s!   € ÷ 	ñ 	�|ð 	°cð 	¸nñ 	r"   c                óp  € V P                  VP                  R4       R2\        4       \        4       R7      p\	        VRR7      pVP                  R4      p\        V\        4      '       d   VP                  R4      '       g5   \        P                  R4       \        \        \        ,          \        4      hV# )	z```POST /api/anonymous/create`` -> ``{user_id, org_id, token, idle_ttl_days}``. Token shown once.Ú/z/api/anonymous/create©rÌ   rÛ   zsign-up)rÓ   ÚtokenÚanon_z-Nous free tier sign-up returned no credential)ÚpostÚrstriprÎ   rí   rã   rL   r]   r(   rÝ   r[   r´   r1   rK   rM   )rï   rñ   rÒ   rß   rõ   s   &&   r#   Ú
mint_guestrù   p  s•   € à�{‰{Ø×!Ñ! #Ó&Ð
'Ð'<Ð=Ä}ÃÔ]nÓ]pð ó r€Hä$ X°iÔ@€GØ�K‰K˜Ó €EÜ�eœS×!Ò!¨×)9Ñ)9¸'×)BÒ)BÜ�‰ÐCÔDÜÔ)Ô*;Õ<Ô>OÓPÐPØ€Nr"   c               ó    € V ^8„  d   QhRRRR/# )r&   rõ   r	   r*   rR   r   )r+   s   "r#   r,   r,   �  s   € ÷ Fñ F˜cð F dñ Fr"   c                óÂ   € ^ RI Hp \        V 4      pV! VP                  R4      4      V! VP                  R4      4      ,          p\	        V4      ;'       d
    \
        V9  # )zc*token* carries a scope claim and it lacks ``inference:invoke`` (a scopeless JWT reads as today's).)Ú_scope_valuesÚscopeÚscp)Úhermes_cli.auth_nousrü   r   rL   rR   r   )rõ   rü   ÚclaimsÚscopess   &   r#   Úis_connectors_onlyr  �  sM   € å2Ü Ó&€FÙ˜6Ÿ:™: gÓ.Ó/±-ÀÇ
Á
È5Ó@QÓ2RÕR€FÜ�‹<×EÐEÔ7¸vÑEÐEr"   Úskew_secondsc               ó$   € V ^8„  d   QhRRRRRR/# )r&   rc   r	   r  zOptional[int]r*   úOptional[str]r   )r+   s   "r#   r,   r,   ‰  s'   € ÷ Kñ K ð K°}ð KÐP]ñ Kr"   c               ó  aa€ ^ RI Ho \        V \        4      '       g   R# T \	        V 4      '       d   V P                  R4      MR3pV Uu. uFm  p\        V\        4      '       g   K  \        VP                  R4      \        4      '       g   KB  VR,          '       g   KS  VR,          VP                  R4      3NKo  	  pp\        VV3R lV 4       R4      pT;'       g    V'       d   Sf   V^ ,          ^ ,          # R# u upi )a  The bearer a connectors / managed-tools call sends: the profile's token (for a guest the
inference one, a superset), else a guest's connectors-only token, preferring one that outlives
*skew_seconds*. ``None`` also accepts an expiring token (availability probes).)Ú_is_expiringNÚconnectors_tokenÚaccess_tokenÚ
expires_atc              3  ób   <"  € T F$  w  rS! TS;'       g    ^ 4      '       d   K   Vx € K&  	  R# 5i)rš   Nr   )Ú.0rõ   Úexpr  r  s   &  €€r#   Ú	<genexpr>Ú(held_connectors_token.<locals>.<genexpr>“  s'   øé € ÐZ©™:˜5±\À#À|×GXÐGXÐWX×5Y—’«ùs   ƒ/–
/¥
/)r}   r  r]   r^   rh   rL   r(   Únext)rc   r  ÚslotsrE   ÚheldÚliver  s   &d    @r#   Úheld_connectors_tokenr  ‰  sÙ   ù€ õ -Ü�eœT×"Ò"ÙØ´^ÀE×5JÒ5J�E—I‘IÐ0Ô1ÐPTÐU€EÙ>Có e¹e¸Ü˜!œT×"ô 5Ü'1°!·%±%¸Ó2GÌ×'Mô 5ØRSÐTb×RcÑRcô 5ˆQˆ~Õ §¡ lÓ 3Ó4¹e€Dð eäÕZ©ÓZÐ\`Óa€DØ×JÐJ§$¨<Ò+?�D˜•G˜A•JÐJÀTÐJùòes   ÁC?Á("C?ÂC?Â C?c               ó0   € V ^8„  d   QhRRRRRRRRRRR	R/# )
r&   rï   rð   rñ   r(   Ú
anon_tokenÚ
auth_staterÔ   Úpurposer*   r   )r+   s   "r#   r,   r,   —  s>   € ÷ &ñ &Øð&Ø+.ð&Ø<?ð&ØP^ð&àð&ð ñ&r"   c               ó(  aaaa
€ ^ RI Ho
 V P                  SP                  R4       R2\	        4       RSRS
P                  4       RV/R7      pR V
VVV3R	 llpR
 V
3R llpR R lp\        VRRVRVRVRVRV/R7      p	\        V	P                  R4      \        4      '       d   V	R,          '       g5   \        P                  R4       \        \        \        ,          \        4      h\        V	R,          4      '       g   S
P!                  V	S4       V	# )a‚  ``POST /api/anonymous/token {token}`` -> ``{access_token, expires_in, inference_base_url, ...}``.

Raises :class:`AnonCredentialDead` on 404 ``unknown_token`` / 401 (reaped or claimed), and
:class:`~hermes_cli.anon_challenge.AnonChallengeRequired` (carrying what the status poll needs:
portal, credential, and the *auth_state* whose ``tls`` block the mint used) on a browser challenge.
)Úanon_challengeró   z/api/anonymous/tokenrõ   rï   r  rô   c               ó    € V ^8„  d   QhRRRR/# ©r&   ÚbodyrÔ   r*   r   r   )r+   s   "r#   r,   Ú'exchange_anon_jwt.<locals>.__annotate__¦  s   € ÷ añ a˜ð a¨9ñ ar"   c                ó.   <€ SP                  V SSSR 7      # ))rñ   r  r  )Úchallenge_error)r  r  r  r  rñ   s   &€€€€r#   Ú	challengeÚ$exchange_anon_jwt.<locals>.challenge¦  s'   ø€ Ø×-Ñ-Ø /¸jÐU_ð .ó að 	ar"   c               ó    € V ^8„  d   QhRRRR/# r  r   )r+   s   "r#   r,   r  ª  s   € ÷ Iñ I�^ð I¨	ñ Ir"   c                óD   <€ SP                  V P                  R 4      4      # )r'   )Úsignin_required_errorrL   )r  r  s   &€r#   ÚsigninÚ!exchange_anon_jwt.<locals>.signinª  s   ø€ ð ×3Ñ3°D·H±H¸YÓ4GÓHÐHr"   c               ó    € V ^8„  d   QhRRRR/# )r&   Ú_bodyrÔ   r*   r   r   )r+   s   "r#   r,   r  ¯  s   € ÷ Rñ R˜^ð R°	ñ Rr"   c                ó@   € \        \        \        ,          \        4      # r‚   )r1   rK   rÞ   )r)  s   &r#   Úproof_of_workÚ(exchange_anon_jwt.<locals>.proof_of_work¯  s   € äÔ*Ô+<Õ=Ô?PÓQÐQr"   ztoken exchange)rÓ   rÐ   r	  z/Nous free tier token exchange returned no token)é¬  Úchallenge_required)r-  r×   ©r-  N)é“  Úsignin_required)r0  Úaccess_denied)Ú
hermes_clir  r÷   rø   rÎ   Úclient_inforã   r]   rL   r(   r[   r´   r1   rK   rM   r  Únote_optional_challenges)rï   rñ   r  r  r  rÒ   r!  r&  r+  rß   r  s   &ffd$     @r#   Úexchange_anon_jwtr6  —  s	  û€ õ *Ø�{‰{Ø×!Ñ! #Ó&Ð
'Ð';Ð<ÄmÃoØ�z 8¨^×-GÑ-GÓ-IÈ9ÐV]Ð^ð ó `€H÷aó a÷Ið Iõ
Rô
 % XÐ6FØ# Y°¸}ÈkÐ[aØ  &Ð*@À&ðSJô K€Gô �g—k‘k .Ó1´3×7Ò7¸wÀ~×?VÔ?VÜ�‰ÐEÔFÜÔ)Ô*;Õ<Ô>OÓPÐPä˜g nÕ5×6Ò6Ø×/Ñ/°¸ÔIØ€Nr"   c               ó$   € V ^8„  d   QhRRRRRR/# )r&   rc   rÔ   Ú	exchangedr*   ÚNoner   )r+   s   "r#   r,   r,   À  s"   € ÷  %ñ  % >ð  %¸nð  %ÐQUñ  %r"   c                ó�  € ^ RI Hp VR,          p\        V4      p\        P                  ! \
        4      pVP                  R4      p\        V\        \        34      '       d'   \        P                  ! \        V4      \
        R7      pM5T\        \        VP                  R4      ;'       g    R4      R7      ,           p\        V4      '       d   RVRVP                  4       /V R	&   R
# V! VP                  R4      4      ;'       g    \        pVP                  R4      ;'       g+    VP                  R4      ;'       g    V P                  R4      p	\        V	\        \         34      '       d   RP#                  R V	 4       4      p	T P%                  TRT	VP                  4       VP                  4       \'        ^ \        Wu,
          P)                  4       4      4      \+        VP                  R4      ;'       g    \,        4      R7       W€R&   R F&  p
VP                  V
4      '       g   K  W,          W
&   K(  	  V P/                  RR
4       R
# )z¸Write a fresh exchange result into a guest state in place: an inference token (token, expiry,
routing) into the state itself, a connectors-only one into ``connectors_token`` beside it.)Ú)_validate_nous_inference_url_from_networkr	  r  )ÚtzÚ
expires_ini„  )r=   r
  r  NÚinference_base_urlrý   rþ   Ú c              3  ó8   "  € T F  p\        V4      x € K  	  R # 5ir‚   )r(   )r  rE   s   & r#   r  Ú*apply_exchange_to_state.<locals>.<genexpr>Ö  s   é € Ð/© Aœ˜QŸ˜«ùs   ‚ÚBearerrm   )r	  Ú
token_typerý   Úobtained_atr
  r=  rm   Úrefresh_token)Úuser_idÚorg_id)rÿ   r;  r   r   Únowr   rL   r]   ÚintrA   Úfromtimestampr   r  Ú	isoformatr   ÚlistÚtupleÚjoinÚupdater@   Útotal_secondsr(   ro   Úpop)rc   r8  r;  r	  r   rH  r  r
  Úinference_urlrý   Úkeys   &&         r#   Úapply_exchange_to_staterT  À  sË  € õ OØ˜^Õ,€LÜ Ó-€FÜ
�,Š,”sÓ
€CØ
�*‰*�UÓ
€CÜ�#œœU�|×$Ò$Ü×+Ò+¬E°#«J¼3Ô?‰
àœ9¬S°·±¸|Ó1L×1SÐ1SÐPSÓ-TÔUÕUˆ
Ü˜,×'Ò'Ø%3°\À<ÐQ[×QeÑQeÓQgÐ$hˆÐ Ñ!Ùñ ?¸y¿}¹}ÐMaÓ?bÓc÷ 1ð 1Ü0ð à�J‰J�wÓ×JÐJ 6§:¡:¨eÓ#4×JÐJ¸¿	¹	À'Ó8J€EÜ�%œ$¤˜×'Ò'Ø—‘Ñ/©Ó/Ó/ˆØ	‡L�LØ!¨h¸eØ—M‘M“O°
×0DÑ0DÓ0FÜ�qœ#˜zÕ/×>Ñ>Ó@ÓAÓBÜ˜Ÿ™ NÓ3×HÐHÔ7HÓIð	 ô Kð
 #0Ð
ÑÛ$ˆØ�=‰=˜×ÔØ"�ˆE‹Jñ %ð 
‡I�Iˆo˜tÖ$r"   c               ó   € V ^8„  d   QhRR/# rŽ   r   )r+   s   "r#   r,   r,   ã  s   € ÷ Pñ P˜#ñ Pr"   c                 óV   € ^ RI Hp  V ! 4       ;'       g    \        P                  R4      # )rš   ©Ú_nous_portal_env_overrideró   )rÿ   rX  r   rø   rW  s    r#   Ú_portal_base_urlrY  ã  s"   € Ý>Ù%Ó'×BÐBÔ+B×JÑJÈ3ÓOÐOr"   c               ó    € V ^8„  d   QhRRRR/# )r&   rc   r	   r*   r  r   )r+   s   "r#   r,   r,   è  s   € ÷ \ñ \ ð \¨ñ \r"   c                ó˜   € \        V \        4      '       g   R# \        V 4      '       d   V P                  R4      # V P                  R4      # )zžStable identity of a Nous credential: the anon_ token for a guest, the refresh token for an
account. Used to decide whether two stores hold the SAME identity.Nr  rE  )r]   r^   rh   rL   rg   s   &r#   Ú_shared_identity_keyr\  è  s;   € ô �eœT×"Ò"ÙÜ&4°U×&;Ò&;ˆ5�9‰9�\Ó"Ð[ÀÇÁÈ?ÓA[Ð[r"   c          
     ó,   € V ^8„  d   QhRRRRRRRRR	R/# )
r&   rï   rð   Úportalr(   Ú
auth_storerÔ   Úwelcome_claimrR   r*   r   )r+   s   "r#   r,   r,   ð  s1   € ÷ ñ ˜ð ¨sð Àð Ø $ðØ)7ñr"   c               óh  € ^ RI HpHp ^ RIHp \        W4      pR\        R\        RVR,          R\        RVP                  R	4      R
VP                  R
4      RVP                  R4      RVP                  R4      \        V/	pV! VRVRR7       V! V4       V! V4       \        P                  R4       V# )a[  Mint under the caller's locks. The identity is persisted as soon as ``create`` succeeds, BEFORE
the exchange: a 429 or timeout on the exchange must not lose a credential NAS still honours (the
next attempt exchanges the stored one instead of minting again). *welcome_claim* is written in
that same save, so a claimed guest is never left unstamped.)Ú_store_provider_stateÚ_save_auth_store)Ú_write_shared_nous_statere   rm   r  rõ   Ú	client_idrñ   ró   rF  rG  Úidle_ttl_daysrV   F©Ú
set_activez&Nous free tier ready (identity minted))r}   rb  rc  rÿ   rd  rù   rf   ro   ÚANON_CLIENT_IDrø   rL   r   r[   r´   )	rï   r^  r_  r`  rb  rc  rd  Úmintedrc   s	   &&&$     r#   Ú_mint_lockedrk  ð  s¢   € ÷ HÝ=Ü˜Ó'€FàÔ'¨Ô9JØ�f˜W•o {´NØ˜6Ÿ=™=¨Ó-Ø�6—:‘:˜iÓ(¨(°F·J±J¸xÓ4HØ˜Ÿ™ OÓ4Ü˜Mð€Eñ ˜* f¨eÀÕFÙ�ZÔ Ù˜UÔ#Ü
‡K�KÐ8Ô9Ø€Lr"   ç      N@c                  ót   € ] tR tRt$ RtR]R&   R]R&   R]R&   R]R	&   R]R
&   ^tR]R&   R R ltR R ltRt	R# )ÚMintFailurei  zEWhy the last mint for a profile failed and when the next one may run.r(   r)   r'   rR   r/   rA   r$   Ú
not_beforerI  Úattemptsc               ó   € V ^8„  d   QhRR/# )r&   r*   rA   r   )r+   s   "r#   r,   ÚMintFailure.__annotate__  s   € ÷ eñ e˜5ñ er"   c                	óž   € V P                   '       g   R # \        R \        V P                  \        P
                  ! 4       ,
          ^4      4      # )r?   )r/   r@   rD   ro  ÚtimeÚ	monotonic©Úselfs   &r#   Ú	remainingÚMintFailure.remaining  s6   € ð Ÿ.Ÿ.˜.ˆsÐd¬c°#´u¸T¿_¹_ÌtÏ~Ê~ÓO_Õ=_ÐabÓ7cÓ.dÐdr"   c               ó   € V ^8„  d   QhRR/# rå   r   )r+   s   "r#   r,   rr  #  s   € ÷ Uñ U˜Nñ Ur"   c                óÀ   € RV P                   RV P                  RV P                  RV P                  '       d&   \        P                  ! V P                  4       4      /# ^ /# )zœThe wire shape every status RPC carries: ``{error_code, error, retryable, retry_after}``
with ``retry_after`` the seconds still to wait (whole, rounded up).Ú
error_coderÖ   r/   r$   )r)   r'   r/   ÚmathÚceilrx  rv  s   &r#   Ú
as_payloadÚMintFailure.as_payload#  sU   € ð ˜dŸi™i¨°$·,±,ÀÈTÏ^É^Ø¸d¿n¿n¸nœtŸyšy¨¯©Ó)9Ó:ðUð 	UØRSðUð 	Ur"   r   N)
r   r   r   r   r    Ú__annotations__rp  rx  r  r!   r   r"   r#   rn  rn    s<   ‡ áOà
ƒIØƒLØƒOØÓØÓØ€HˆcÓõe÷
Uñ Ur"   rn  zdict[str, MintFailure]Ú_mint_failuresc               ó   € V ^8„  d   QhRR/# rŽ   r   )r+   s   "r#   r,   r,   -  s   € ÷ Kñ K˜ñ Kr"   c                 ó6   € ^ RI Hp Hp V ! 4       f   R# V! 4       # )rš   ©Úget_hermes_home_overrideÚhermes_home_keyrt   )Úhermes_constantsr†  r‡  r…  s     r#   Ú_mint_memo_keyr‰  -  s   € ßJÙ)Ó+Ò3ˆ2ÐJ¹Ó9JÐJr"   c               ó   € V ^8„  d   QhRR/# )r&   r*   zOptional[MintFailure]r   )r+   s   "r#   r,   r,   2  s   € ÷ 0ñ 0Ð#8ñ 0r"   c                 ó<   € \         P                  \        4       4      # r‚   )r‚  rL   r‰  r   r"   r#   Ú_mint_failure_for_profilerŒ  2  s   € Ü×ÑœnÓ.Ó/Ð/r"   c               ó   € V ^8„  d   QhRR/# ©r&   r*   r9  r   )r+   s   "r#   r,   r,   6  s   € ÷ /ñ /˜Tñ /r"   c                 óB   € \         P                  \        4       R 4       R # r‚   )r‚  rQ  r‰  r   r"   r#   Ú_clear_mint_failurer�  6  s   € Ü×Ñ”~Ó'¨Ö.r"   c               ó   € V ^8„  d   QhRR/# rŽ  r   )r+   s   "r#   r,   r,   :  s   € ÷ ñ  4ñ r"   c                 ó.   € \         P                  4        R # r‚   )r‚  Úclearr   r"   r#   Úreset_mint_memo_for_testsr”  :  s   € Ü×ÑÖr"   c               ó   € V ^8„  d   QhRR/# rx   r   )r+   s   "r#   r,   r,   >  s   € ÷ 5ñ 5Ð3ñ 5r"   c                 óJ   € \        4       p V '       d   V P                  4       # R# )z„The most recent mint failure for this profile as a wire payload, or None (never failed, or
cleared by a later success / retirement).N)rŒ  r  )Úfailures    r#   Úlast_mint_failurer˜  >  s"   € ô (Ó)€Gß#*ˆ7×ÑÓÐ4°Ð4r"   c               ó    € V ^8„  d   QhRRRR/# )r&   r~   ÚBaseExceptionr*   r   r   )r+   s   "r#   r,   r,   E  s   € ÷ ñ  ð °9ñ r"   c           	     ó|  € \        V \        4      '       d   V P                  '       d   V # \        \        \
        3p V\        P                  \        P                  3,           p\        W4      '       d   \        M\        p\        \        V,          V\        V RR4      R7      pWn        V#   \         d     LVi ; i)a	  Every mint failure as one ``AuthError`` with a code: the portal's own refusals already are;
the wire's (timeout, DNS, refused connection) and anything else get a code here. Pure: *exc* is
never mutated (an uncoded ``AuthError`` is re-raised as a server-error twin).r$   NrØ   )r]   r   r)   ÚTimeoutErrorÚConnectionErrorÚOSErrorr   ÚTimeoutExceptionÚTransportErrorrZ   ÚANON_UNREACHABLErM   r1   rK   ru   Ú	__cause__)r~   Ú	transportr)   Úwrappeds   &   r#   Úclassify_mint_exceptionr¥  E  s�   € ô �#”y×!Ò! c§h§h hØˆ
Üœ´Ð8€IðØ¤×!7Ñ!7¼×9MÑ9MÐ NÕNˆ	ô  *¨#×9Ò9ÕÔ?P€DÜÔ)¨$Õ/°Ä7È3ÐP]Ð_cÓCdÔe€GØÔØ€Nøô ô Ùðús   ½'B- Â-B;Â:B;c               ó    € V ^8„  d   QhRRRR/# )r&   Úerrr   r*   rn  r   )r+   s   "r#   r,   r,   V  s   € ÷ ñ ˜Ið ¨+ñ r"   c           	     ód  € \        V P                  ;'       g    \        4      p\        4       pV'       d%   VP                  V8X  d   VP                  ^,           M^pV\
        9  pV'       g   R\        R4      reM�V P                  pV'       d   \        V4      M*\        \        V\        \        4      4      ^,
          ,          pV\        8X  d   \        V\        4      p\        RV4      p\        P                  ! 4       V,           p\!        V\        V 4      WEWcR7      pV\"        \%        4       &   V# )é   r?   Úinfg      ð?)r)   r'   r/   r$   ro  rp  )r(   r)   rM   rŒ  rp  r0   rA   r$   Ú_MINT_RETRY_LADDERÚminÚlenÚANON_GATE_PAUSEDr@   Ú_MINT_PAUSED_MIN_WAITrt  ru  rn  r‚  r‰  )	r§  r)   Úpreviousrp  r/   rJ   ro  Úhintedr—  s	   &        r#   Ú_note_mint_failurer²  V  så   € Üˆs�x‰x×,Ð,Ô,Ó-€DÜ(Ó*€Hß(0°X·]±]ÀdÔ5Jˆx× Ñ  1Ö$ÐPQ€HØÔ/Ñ/€IßØ¤ e£‰jà—‘ˆß &Œu�VŒ}Ô,>¼sÀ8ÌSÔQcÓMdÓ?eÐhiÕ?iÕ,jˆØÔ#Ô#Ü�tÔ2Ó3ˆDÜ�3˜‹~ˆÜ—^’^Ó%¨Õ,ˆ
Ü˜t¬S°«XÀØ%/ôD€Gà'.„N”>Ó#Ñ$Ø€Nr"   ÚforceFr`  c               ó(   € V ^8„  d   QhRRRRRRRR/# )r&   Útimeout_secondsrA   r³  rR   r`  r*   ry   r   )r+   s   "r#   r,   r,   j  s*   € ÷ -#ñ -#°ð -#¸tð -#Ø,0ð-#Ø=Uñ-#r"   c                ód  € ^ RI HpHpHpHpHpHp ^ RIHp	H	p
H
pHp \        4       pV! 4       ;_uu_ 4        V! 4       pV! VR4      pV
! \        V R4      R7      ;_uu_ 4        V! 4       pV'       dr   \        V4      \        V4      8w  dY   \        V4      pV! VRV\!        V4      '       * R7       V! V4       \"        P%                  R4       VuuRRR4       uuRRR4       # V'       d'   V'       g	   V! V4       VuuRRR4       uuRRR4       # \'        4       pV'       d@   V'       g8   \(        P*                  ! 4       VP,                  8  d    RRR4       RRR4       R# V! RRRR	7      p V	! V V4      ;_uu_ 4       p\/        VWÞVR
7      uuRRR4       uuRRR4       uuRRR4       #   + '       g   i     M;; i  \0         d+   p\3        T4      p\5        T4      Tn        TTJ d   h TThRp?ii ; i RRR4       M  + '       g   i     M; iRRR4       R#   + '       g   i     R# ; i)a¾  The lifecycle body, run under profile lock THEN shared lock (the documented order).

1. The shared store is the identity of record for this Hermes root. If it holds an identity
   that differs from the profile's, the profile adopts it (a stale guest never outlives a
   sibling profile's sign-in, and never overwrites it).
2. Otherwise the profile's own identity stands.
3. Nothing anywhere: mint, persisting the credential before exchanging it.
)Ú_auth_store_lockr{   r|   rc  rb  Ú_resolve_verify)Ú_nous_http_clientÚ_nous_shared_store_lockÚ_read_shared_nous_staterd  rV   r   )rµ  rg  z+Nous identity adopted from the shared storeN)ÚinsecureÚ	ca_bundler  )r`  )r}   r·  r{   r|   rc  rb  r¸  rÿ   r¹  rº  r»  rd  rY  r@   r\  r^   rh   r[   r\   rŒ  rt  ru  ro  rk  rZ   r¥  r²  Úmint_failure)rµ  r³  r`  r·  r{   r|   rc  rb  r¸  r¹  rº  r»  rd  r^  r_  Úprofile_stateÚsharedrc   r—  Úverifyrï   r~   r§  s   $$$                    r#   Ú_reconcile_and_provisionrÂ  j  sÁ  € ÷0÷ 0÷gó gäÓ€FÙ	×	Õ	Ù%Ó'ˆ
Ù,¨Z¸Ó@ˆÙ$´S¸È#Ó5N×OÖOÙ,Ó.ˆFßÔ.¨vÓ6Ô:NÈ}Ó:]Ô]Ü˜V›�Ù% j°&¸%ÔP^Ð_dÓPeÔLeÕfÙ  Ô,Ü—‘ÐJÔKØ÷ PÑO÷ 
Ò	÷ ßÙ,¨]Ô;Ø$÷ PÑO÷ 
Ò	ô  0Ó1ˆGßŸu¬¯ªÓ)9¸G×<NÑ<NÔ)NØ÷ P÷ 
Ñ	ñ& %¨d¸dÈtÔTˆFð	#Ù& ¸×?Ô?À6Ü'¨°ÐR_Ô`÷ @Ñ?÷% PÑO÷ 
Ò	÷* @×?ûäô #ä-¨cÓ2�Ü#5°cÓ#:�Ô Ø˜#“:ØØ˜sÐ"ûð#úð @÷% P×O×OÐOú÷ 
×	×	Ò	ús¢   ¶,HÁ"A,H	Ã
HÃ#H	Ã+H	Ã3	H	Ã<
HÄH	Ä+%H	ÅHÅ"H	Å.F?Å?F,Æ
F?Æ
HÆ,F<Æ7F?Æ;H	Æ<F?Æ?G4Ç
%G/Ç/G4Ç4H	Ç8	HÈHÈHÈH/	rµ  c          
     ó,   € V ^8„  d   QhRRRRRRRRRR/# )	r&   ÚexplicitrR   rµ  rA   r³  r`  r*   ry   r   )r+   s   "r#   r,   r,   š  s6   € ÷ 0ñ 0Øð0Ø(-ð0ØSWð0àð0ð ñ0r"   c           	     ól  € V '       g   \        R4      h\        4       '       g   R# \        4       pV'       d?   V'       g7   \        4       '       g'   \        P
                  ! 4       VP                  8  d   R#  \        WVR7      pTe   \%        4        ^ R
IHp	 T	! 4        T#   \         dˆ   p\        T4      p\        TRR4      ;'       g    \        T4      p\        P                  RTP                  TP                  TP                   '       d   RTP"                  R R2MR	4       YvJ d   h YvhRp?ii ; i)a«  Make sure this profile has a Nous identity (guest or account); mint a guest only if the shared
store has none. Returns the ``providers.nous`` state, or None (disabled / failed once already).

``explicit`` is required and must be True: the only callers are the first hosted connector action
(``tools.connectors.gateway.config.ensure_guest_identity``), the connectors dead-credential
replacement (``managed_tool_gateway._replace_dead_guest_token``) and the desktop's welcome-trial
claim (``welcome_trial.claim_desktop_free_tier``), which passes ``welcome_claim=True`` so a guest
it mints carries the stamp from its first write. Every other guest is minted with
``welcome_claim: False`` and serves connectors only.
Nothing creates an identity as a side effect of reading status, resolving a provider or fetching a
connector bearer (NS-845 Q1.2).

Order: gate (``guest_allowed``) -> reconcile with the shared store -> mint. Locks are taken
profile first, then shared, matching every other Nous path. Blocking, bounded by ``timeout_seconds``.

A failed mint is memoised with a cooldown (``MintFailure``): until it passes, and for a
terminal code forever, this returns None without touching the portal. ``force=True`` is the
user's own retry: it makes exactly one attempt
regardless of the cooldown. Every failure raises an ``AuthError`` whose ``code`` is one of the
``ANON_*`` codes and whose ``retry_after`` / ``retryable`` say what a caller may do next.
zLensure_portal_identity: only explicit creators may call this (explicit=True)N)rµ  r³  r`  r¾  z,Nous free tier not set up (%s, attempt %d%s)z, next try in z.0frE   z, not retried)Údrain)rC   r`   rŒ  r   rt  ru  ro  rÂ  rZ   r¥  ru   r²  r[   r´   r)   rp  r/   r$   r�  Úhermes_cli.guest_handoffrÆ  )
rÄ  rµ  r³  r`  r—  rc   r~   r§  ÚnotedrÆ  s
   $$$$      r#   Úensure_portal_identityrÉ  š  s   € ÷2 ÜÐgÓhÐhÜ�?Š?ÙÜ'Ó)€Gß—uÔ%7×%9Ò%9¼d¿nºnÓ>NÐQX×QcÑQcÔ>cÙð
Ü(¸Ø7DôFˆð ÒÜÔå2ÙŒØ€Løô ô Ü% cÓ*ˆÜ˜˜^¨TÓ2×MÐMÔ6HÈÓ6MˆÜ�‰ÐBÀEÇJÁJÐPU×P^ÑP^ØAFÇÇÀ�n U×%6Ñ%6°sÐ$;¸1Ñ=ÐVeô	gà‹:ØØÐûðús   Á7B! Â!D3Â,A"D.ÄD.Ä.D3c               ó(   € V ^8„  d   QhRRRRRRRR/# )r&   rc   rÔ   rï   rð   r  r(   r*   r   )r+   s   "r#   r,   r,   Í  s*   € ÷ %ñ %˜~ð %°|ð %ÐQTð %ÐY\ñ %r"   c               óH  € VR8X  d    \        V 4      '       g   \        RRRR7      hV P                  R4      p\        V\        4      '       d	   V'       g!   \        \        \        ,          \        R7      h^ RIH	p \        W! V 4      W0VR	7      p\        W4       VR
,          # )aI  Token-acquisition seam for a guest: re-exchange the ``anon_`` credential in place and return
the minted token. Every caller names its *purpose*: ``"connectors"`` for connector and managed-tool
bearers, ``"inference"`` only for a guest that carries the welcome trial.

The portal URL is the resolver's canonical one (env override, else the validated stored URL,
else the default), never a raw stored value on its own.
Raises :class:`AnonCredentialDead` when NAS no longer knows the credential; the caller owns
re-minting (:func:`ensure_portal_identity` after :func:`clear_dead_guest`).
Ú	inferencez&Hermes is not logged into Nous Portal.rV   Únous_auth_missing)rj   r)   r  )r)   )Ú_nous_portal_base_url)r  r  r	  )rŒ   r   rL   r]   r(   r   rK   ÚANON_CREDENTIAL_DEADr}   rÎ  r6  rT  )rc   rï   r  r  rÎ  r8  s   &&$   r#   Úrefresh_guest_staterÐ  Í  s�   € ð �+ÔÔ&;¸E×&BÒ&Bô Ð@È6ÐXkÔlÐlØ—‘˜<Ó(€JÜ�j¤#×&Ò&¯jÜ Ô!2Ô3GÕ!HÔOcÔdÐdÝ5Ü!ØÐ% eÓ,¨jÐT[ô]€Iä˜EÔ-Ø�^Õ$Ð$r"   Ú
dead_tokenc               ó$   € V ^8„  d   QhRRRRRR/# )r&   Úreasonr(   rÑ  r  r*   r9  r   )r+   s   "r#   r,   r,   å  s&   € ÷ añ a˜Sð a°ð aÈ$ñ ar"   c          	     óò  € ^ RI HpHpHpHpHp ^ RIHpHpH	p	 V! 4       ;_uu_ 4        V! 4       p
V! V
R4      p\        V4      '       dˆ   T;'       g    VP                  R4      pVP                  R4      V8X  dV   V! V
R4      P                  RR4       V! V
R4      P                  RR4       V
P                  R4      R8X  d   RV
R&   V! V
4       MTpV! 4       ;_uu_ 4        V	! 4       pV'       d0   \        V4      '       d   VP                  R4      V8X  d	   V! V 4       RRR4       RRR4       \        4        \        P                  R	V 4       R#   + '       g   i     L:; i  + '       g   i     LE; i)
a@  Drop a dead guest so the next need re-mints.

Only the identity that actually failed is removed: a stale profile whose credential NAS rejected
must not erase a sibling profile's newer sign-in or replacement guest from the shared store. When
*dead_token* is None the profile's current guest is treated as the failed one.
)r·  r{   r|   rc  Ú_store_section)Ú_clear_shared_nous_staterº  r»  rV   r  Ú	providersNÚcredential_poolÚactive_providerzENous free-tier identity retired (%s); a new one is set up on next use)r}   r·  r{   r|   rc  rÕ  rÿ   rÖ  rº  r»  rh   rL   rQ  r�  r[   r´   )rÓ  rÑ  r·  r{   r|   rc  rÕ  rÖ  rº  r»  r_  rc   rõ   rÀ  s   &$            r#   Úclear_dead_guestrÚ  å  s(  € ÷dõ dçoÑoÙ	×	Õ	Ù%Ó'ˆ
Ù$ Z°Ó8ˆÜ˜%× Ò Ø×9Ð9 %§)¡)¨LÓ"9ˆEØ�y‰y˜Ó&¨%Ô/Ù˜z¨;Ó7×;Ñ;¸FÀDÔIÙ˜zÐ+<Ó=×AÑAÀ&È$ÔOØ—>‘>Ð"3Ó4¸Ô>Ø48�JÐ0Ñ1Ù  Ô,øàˆEÙ$×&Õ&Ù,Ó.ˆFßœ¨×/Ò/°F·J±J¸|Ó4LÐPUÔ4UÙ(¨Ô0÷ '÷ 
ô" ÔÜ
‡K�KÐWÐY_Ö`÷ '×&ú÷ 
×	ús*   ¨*E&ÁBE&Ã"?E	Ä!E&ÅE#ÅE&Å&E6	zx-nous-model-switchÚmodel_not_freeÚfeature_not_freeÚanon_on_paid_hostÚnamed_on_welcome_hostÚtier_disabledÚsession_expiredz‚This install is set to use a different Nous server (NOUS_INFERENCE_BASE_URL). Unset it to use the free model, or sign in. {signin}z2This Nous account needs to reconnect. {model_hint}zhUsing Hermes without signing in is switched off right now. Sign in to keep chatting, it's free. {signin}z�Hermes couldn't renew its connection to the free model. Send your message again, or sign in to keep chatting, it's free. {signin}zTo sign in: /login.z"To sign in: `hermes auth upgrade`.z'Run /model and pick the Nous row again.z/Run `hermes model` and pick the Nous row again.zbThe free model is having trouble responding right now. Try sending your message again in a minute.c               ó    € V ^8„  d   QhRRRR/# )r&   r  r	   r*   ry   r   )r+   s   "r#   r,   r,   2  s   € ÷ Pñ P ð PÐ(@ñ Pr"   c                ó|  € \        V \        4      '       g   R# V P                  R4      p\        V\        4      '       d   V\        9  d   R# V P                  R4      p VR9  d   \        ^ \        \        V4      4      4      M^ pV P                  R4      p\        V\        4      '       d>   V Uu. uF0  p\        V\        4      '       g   K  V'       g   K%  \        V4      NK2  	  upM. pV P                  R4      pRTRTRTR\        V\        4      '       d   V/# R/#   \        \        3 d    ^ p L¯i ; iu upi )a  The structured welcome-tier refusal in a gateway 429 body, or None for any other shape.

Returns ``{"reason", "retry_after", "alternates", "upgrade_url"}`` with ``retry_after`` an int
of whole seconds (0 when the gateway sent none) and ``alternates`` a list of model ids.
NrÓ  r$   rt   Ú
alternatesÚupgrade_url)Nrt   )r]   r^   rL   r(   ÚWELCOME_REFUSAL_REASONSr@   rI  rA   rB   rC   rL  )r  rÓ  Ú	raw_retryr$   Úraw_alternatesÚarã  rä  s   &       r#   Úparse_welcome_refusalré  2  s  € ô �dœD×!Ò!ÙØ�X‰X�hÓ€FÜ�fœc×"Ò" fÔ4KÔ&KÙØ—‘˜Ó'€IðØ7@È
Ô7R”c˜!œS¤ yÓ!1Ó2Ô3ÐXYˆð —X‘X˜lÓ+€NÜQ[Ð\jÔlp×QqÒQq¡.ÓM¡.˜Q´J¸qÄ#×4F”&Ì1”&”#�a–&¡.ÒMÐwy€JØ—(‘(˜=Ó)€KØ�f˜m¨[¸,È
Ø¬*°[Ä#×*FÒ*F˜;ðPð PØLNðPð Pøô ”zÐ"ô ØŠðüò Ns$   Á'D  Â1D9ÃD9ÃD9Ä D6Ä5D6r±   rt   Úin_chatTÚdoorc          
     ó,   € V ^8„  d   QhRRRRRRRRRR/# )	r&   ÚrefusalrÔ   r±   r(   rê  rR   rë  r*   r   )r+   s   "r#   r,   r,   I  s8   € ÷ bñ b .ð b¸Cð bÈtð bÐbfð bÐruñ br"   c               ó¾  € V'       d   V'       d   \         M\        MRp\        V P                  R4      ;'       g    R4      pV P                  R4      ;'       g    . pV'       d
   V^ ,          M\        p\        V P                  R4      ;'       g    ^ 4      pV^ 8”  d   \        V4      MRp	VR8X  d(   V'       d   V R2MRp
V
 R	V R
V 2P                  4       # VR8X  d   RV 2P                  4       # VR8X  d   RV	 RV 2P                  4       # VR8X  d   RV	 RV 2P                  4       # VR8X  d   RV	 RV 2P                  4       # RV 2P                  4       # )uG  User copy for a structured welcome-tier refusal: what happened and the one way forward.

Never guest / anonymous / claim; ``in_chat`` picks ``/login`` over the terminal verb.
``door=False`` leaves the "To sign in: â€¦" tail off, for a surface that renders the sign-in as
a button beside the sentence (the desktop's error card).rt   rÓ  rã  r$   za little whilerÛ  z isn'tzThat model isn'tz. available without signing in, so Hermes uses z# for now. Sign in for more models. rÜ  zGThat isn't available without signing in. Sign in to use it, it's free. Úat_capacityzlChatting without signing in is really busy right now. Sign in to skip the queue, it's free, or try again in z. Úadmission_closedzaChatting without signing in is full right now. Sign in to keep going, it's free, or try again in Úrate_limitedzNYou've used up the allowance for chatting without signing in. It refreshes in z-. Sign in for a bigger allowance, it's free. zBHermes couldn't send that without signing in. Signing in is free. )Ú_SIGNIN_CHATÚ_SIGNIN_TERMINALr(   rL   r�   rI  rG   rø   )rí  r±   rê  rë  r&  rÓ  rã  ÚservesÚretryrJ   Úwhats   &$$$       r#   Úwelcome_refusal_copyr÷  I  s~  € ÷ AEŸg�lÕ+;È"€FÜ�—‘˜XÓ&×,Ð,¨"Ó-€FØ—‘˜\Ó*×0Ð0¨b€Jß(ˆZ˜Ž]¬k€FÜ�—‘˜MÓ*×/Ð/¨aÓ0€EØ#(¨1¤9Œ=˜ÔÐ2B€DØÐ!Ô!ß#(�%�˜ÑÐ.@ˆØ�&ÐFÀvÀhð O,Ø,2¨8ð5ß6<±f³hð	?àÐ#Ô#ØXÐY_ÐX`Ða×hÑhÓjÐjØ�Ôð.Ø.2¨V°2°f°Xð?ß@FÁÃð	IàÐ#Ô#ð.Ø.2¨V°2°f°Xð?ß@FÁÃð	Ià�ÔØ`ÐaeÐ`fð g>Ø>D¸XðGßHNÉËð	QàOÐPVÈxÐX×_Ñ_ÓaÐar"   c               ó(   € V ^8„  d   QhRRRRRRRR/# )r&   rà   r	   r'   r°   r*   r  r   )r+   s   "r#   r,   r,   g  s(   € ÷ ñ  #ð °ð ¸sð Èmñ r"   c                óÐ   a€ V R9  d   R# \        T;'       g    R4      P                  4       o\        V3R l\         4       R4      pVf   V R8X  d   \	        V4      '       d   R# V# )aý  Which host cross-refusal a gateway 400/403 is; None for any other error.

``"anon_on_paid_host"``: a free-tier JWT reached the paid host. ``"named_on_welcome_host"``: an
account or API key reached the free tier's host. ``"tier_disabled"``: the tier is dark
(``WELCOME_MODE=off``). Each is deterministic for the request: retrying cannot help.
``"session_expired"``: the 403 names the bearer (``invalid jwt``); a fresh credential heals it.

The dark-tier 403 is keyed on the ROUTE, not the message: the gateway's permission error
carries only its generic sentence (the detail stays in its logs), so any 403 answered by the
welcome host means the tier refused this install. The message needles remain for gateways
that do spell it out, and for the two wrong-host 400s.r0  Nrt   c              3  ó>   <"  € T F  w  rVS9   g   K  Vx € K  	  R # 5ir‚   r   )r  ÚneedleÚkindÚtexts   &  €r#   r  Ú(welcome_route_refusal.<locals>.<genexpr>v  s   øé € ÐTÑ*A™,˜&ÀVÈtÁ^—’Ó*Aùs   ƒ“
rß  )i�  r0  )r(   r¨   r  Ú_WELCOME_ROUTE_REFUSALSr³   )rà   r'   r°   rü  rý  s   &&& @r#   Úwelcome_route_refusalr   g  s[   ø€ ð �ZÔÙÜˆw�}ˆ}˜"Ó×#Ñ#Ó%€DÜÔTÕ*AÓTÐVZÓ[€DØ‚|˜ #œÔ*?À×*IÒ*IÙØ€Kr"   c               ó(   € V ^8„  d   QhRRRRRRRR/# )r&   rü  r(   rê  rR   rë  r*   r   )r+   s   "r#   r,   r,   |  s/   € ÷ Sñ S Sð S°dð SÈð SÐY\ñ Sr"   c               óè   € \         P                  V 4      ;'       g    R pTP                  \        V'       d   V'       d   \        M\
        MRV'       d   \        M\        R7      P                  4       # )z3Hermes couldn't reach the free model on this route.rt   )r¿   r&  Ú
model_hint)	Ú_WELCOME_ROUTE_COPYrL   r+   r   rò  ró  Ú_MODEL_HINT_CHATÚ_MODEL_HINT_TERMINALrø   )rü  rê  rë  rN   s   &$$ r#   Úwelcome_route_refusal_copyr  |  sS   € Ü"×&Ñ& tÓ,×eÐeÐ0e€HØ�?‰?Ü%×ae¿w­|ÕL\Ðkmß'.Õ#Ô4Hð ó JçJPÉ&Ë(ðSr"   c               ó$   € V ^8„  d   QhRRRRRR/# )r&   rr   r	   rÌ   r*   r  r   )r+   s   "r#   r,   r,   ƒ  s!   € ÷ ñ ˜Sð ¨3ð °=ñ r"   c                ó´  € Vf   R# Rp VP                  \        4      pVf4   \        VR4      '       d"   \        R VP	                  4        4       R4      p\        T;'       g    R4      P                  4       pT'       g   R# \        \        T RR4      ;'       g    R4      pY48X  d   R#  YC3T n	        T#   \
         d     R# i ; i  \
         d     R# i ; i)aÔ  Record the gateway's ``x-nous-model-switch`` header on *agent* for the next call, if present.

The header arrives on a NAMED account's response that asked for ``nous/welcome`` (the gateway
served the backing model and billed it normally): the free tier's model no longer belongs in
this install's configuration. Recorded here, applied by :func:`apply_model_switch` between
calls so a response still streaming is never re-labelled under itself. Returns the backing id.
NÚitemsc              3  ór   "  € T F-  w  r\        V4      P                  4       \        8X  g   K)  Vx € K/  	  R # 5ir‚   )r(   r¨   ÚMODEL_SWITCH_HEADER)r  ÚkÚvs   &  r#   r  Ú$note_model_switch.<locals>.<genexpr>‘  s&   é € Ða©¡ ¼3¸q»6¿<¹<»>ÔM`Ñ;`Ÿ!š!«ùs   ‚&7­
7rt   r±   )
rL   r  Úhasattrr  r
  rZ   r(   r§   ru   Ú_nous_pending_model_switch)rr   rÌ   ÚvalueÚbackingÚ	requesteds   &&   r#   Únote_model_switchr  ƒ  sÒ   € ð ‚ÙØ€EðØ—‘Ô/Ó0ˆØŠ=œW W¨g×6Ò6ÜÑa¨¯©¬ÓaÐcgÓhˆEô �%—+�+˜2Ó×$Ñ$Ó&€GßÙÜ”G˜E 7¨BÓ/×5Ð5°2Ó6€IØÔÙðØ,5Ð+?ˆÔ(ð €Nøô ô Úðûô ô Úðús$   ŠAB6 Â,C Â6CÃCÃCÃCc               ó    € V ^8„  d   QhRRRR/# )r&   rr   r	   r*   r  r   )r+   s   "r#   r,   r,   ¡  s   € ÷ 'ñ '˜cð ' mñ 'r"   c           
     óZ  € \        V RR4      pV'       g   R# RV n        Vw  r#\        \        V RR4      ;'       g    R4      V8w  d   R# Y0n        W#3V n        \
        P                  RW#4        ^ RIHp V! 4       P                  R4      p\        V\        4      '       d   TM\        V\        4      '       d   RV/M/ p\        VP                  R4      ;'       g    R4      P                  4       V8X  dF   ^ RIHp T! R	\        \        V R
R4      ;'       g    R4      VR7       \
        P                  RW#4       \        T RR4      p	\#        T	4      '       d    T	! RT RT R24       T# T#   \         d!   p\
        P!                  RT4        Rp?LXRp?ii ; i  \         d     T# i ; i)aý  Move *agent* (and the config default, when it still names the switched id) to the backing
model the gateway named. Returns the new model, or None when nothing was pending.

Runs once per recorded header, between calls. The conversation keeps its history; only the id
the next request carries changes, so a promoted account stops relying on the gateway's reverse
map. The config write is the same one a sign-in completion uses, so ``hermes model`` and the
gateway's config re-read agree with the live session.
r  Nr±   rt   z?Nous gateway asked to switch %s -> %s; applied for this sessionrT   Údefault©Ú_update_config_for_providerrV   r°   )Údefault_modelz#Config default model moved %s -> %sz+model switch: config default left as is: %sÚ_buffer_statuszModel is now z (your account's model; z is the free tier's).)ru   r  r(   r±   Ú_nous_model_switchr[   r´   rY   rU   rL   r]   r^   r§   r}   r  rZ   r\   Úcallable)
rr   Úpendingr  r  rU   r«   Ú	model_cfgr  r~   rà   s
   &         r#   Úapply_model_switchr!  ¡  s”  € ô �eÐ9¸4Ó@€GßÙØ'+€EÔ$Ø Ñ€IÜ
Œ7�5˜' 2Ó&×,Ð,¨"Ó-°Ô:ÙØ„Kð !*Ð3€EÔÜ
‡K�KÐQÐS\Ôfð
IÝ:Ù"Ó$×(Ñ(¨Ó1ˆÜ% c¬4×0Ò0‘CÌ:ÐVYÔ[^×K_ÒK_¸	À3Ñ7GÐegˆ	Üˆy�}‰}˜YÓ'×-Ð-¨2Ó.×4Ñ4Ó6¸)ÔCÝCÙ'ØœœG E¨:°rÓ:×@Ð@¸bÓAÐQXõZä�K‰KÐ=¸yÔRô �UÐ,¨dÓ3€FÜ�×Òð	Ù�] 7 )Ð+CÀIÀ;ÐNcÐdÔeð €Nˆ7€Nøô ô IÜ�‰ÐBÀC×HÑHûðIûô ô 	ØØ€Nð	ús7   Á/A,E- Ã;E- Ä#E- ÅF Å-FÅ8FÆFÆF*Æ)F*Úguest_notice_shownc               ó   € V ^8„  d   QhRR/# rQ   r   )r+   s   "r#   r,   r,   Ñ  s   € ÷ Sñ S˜dñ Sr"   c                 ó‚   € \        4       p \        V 4      ;'       d$    \        V P                  \        4      4      '       * # )zZTrue when a guest identity exists and the one-time availability notice has not been shown.)r   rŒ   rR   rL   ÚGUEST_NOTICE_FLAGrg   s    r#   Úguest_notice_pendingr&  Ñ  s/   € äÓ €EÜ  Ó'×RÐR´°U·Y±YÔ?PÓ5QÓ0RÔ,RÐRr"   c               ó   € V ^8„  d   QhRR/# rQ   r   )r+   s   "r#   r,   r,   ×  s   € ÷ 9ñ 9 ñ 9r"   c                 ó$   € \        \        4      RJ# )z¯Persist ``guest_notice_shown`` on the guest's ``providers.nous`` state (whichever store holds it).

Returns True when a flag was written; False when there is no guest to mark.N)Úset_guest_flagr%  r   r"   r#   Úmark_guest_notice_shownr*  ×  s   € ô Ô+Ó,°DÐ8Ð8r"   c               ó    € V ^8„  d   QhRRRR/# )r&   Úflagr(   r*   ry   r   )r+   s   "r#   r,   r,   Þ  s   € ÷ ñ ˜ð Ð!9ñ r"   c                ó   € ^ RI Hp V! R4      ;_uu_ 4       w  r#p\        V4      '       d   Vf    RRR4       R# VP                  V 4      '       d   VuuRRR4       # / VCV R/Cp\	        W#V4       RRR4       V#   + '       g   i     X# ; i)zŠSet *flag* on the guest's ``providers.nous`` state in whichever store holds it, and return the
updated state; None when there is no guest.)Ú_provider_state_transactionrV   NT)r}   r.  rh   rL   Ú_save_guest_state)r,  r.  r_  rc   Úsource_paths   &    r#   r)  r)  Þ  s‡   € õ <Ù	$ V×	,Ô	,Ñ0P°ÀKÜ˜e×$Ò$¨Ò(;Ø÷ 
-Ñ	,ð �9‰9�T�?Š?Ø÷	 
-Ò	,ð
 &�5Ð%˜$ Ñ%ˆÜ˜*¨[Ô9÷ 
-ð €L÷ 
-Ö	,ð €Lús   —A<»A<ÁA<ÁA<Á<B	c               ó(   € V ^8„  d   QhRRRRRRRR/# )r&   r_  rÔ   rc   r0  r   r*   r9  r   )r+   s   "r#   r,   r,   ì  s0   € ÷ 	@ñ 	@ .ð 	@¸ð 	@ÐVZð 	@Ð_cñ 	@r"   c                óª   € ^ RI HpHpHpHpHp V! W#! 4       4      '       d   W! V R4      R&   V! V 4       R# V! V4      pW! VR4      R&   V! W‚R7       R# )zdWrite the guest's ``providers.nous`` back to the store it was read from (the caller holds its lock).)Ú_auth_file_pathr{   Ú
_same_pathrc  rÕ  r×  rV   )Útarget_pathN)r}   r3  r{   r4  rc  rÕ  )	r_  rc   r0  r3  r{   r4  rc  rÕ  Úsource_stores	   &&&      r#   r/  r/  ì  sT   € çoÕoÙ�+˜Ó0×1Ò1Ø:?ˆ�z ;Ó/°Ñ7Ù˜Ö$á'¨Ó4ˆØ<Aˆ�| [Ó1°&Ñ9Ù˜×?r"   Úoauth_device_codec               ó4   € V ^8„  d   QhRRRRRRRRRR	R
RRR/# )r&   Ú
token_datarÔ   rñ   r(   re  rý   r  rÁ  r	   rµ  rA   r*   r   )r+   s   "r#   r,   r,     sF   € ÷ ñ ØðØ47ðØDGðØP]ðØgjðàðð ñr"   c               ó&  € ^ RI HpHpHpHp	 ^ RIHp
HpHp \        P                  ! \        4      pV! V P                  R^ 4      4      pV! V P                  R4      4      ;'       g#    VR,          P                  P                  R4      pRTRTRTR	V P                  R	4      ;'       g    TR
V P                  R
R4      RV R,          RV P                  R4      RVP                  4       RV! WÞ4      RVRV	! V4      /V
CpV! VVRR7      p\         VR&   V# )zbThe ``providers.nous`` shape for the signed-in account (same fields the device-code login writes).)ÚPROVIDER_REGISTRYÚ_coerce_ttl_secondsÚ_optional_base_urlÚ_tls_state_from_verify)Ú_NOUS_EMPTY_AGENT_KEY_FIELDSÚ
_iso_afterÚrefresh_nous_oauth_from_stater=  r>  rV   ró   rñ   re  rý   rC  rB  r	  rE  rD  r
  ÚtlsF)rµ  Úforce_refreshre   )r}   r;  r<  r=  r>  rÿ   r?  r@  rA  r   rH  r   rL   r>  rø   rK  ÚUPGRADED_AUTH_METHOD)r9  rñ   re  rý   rÁ  rµ  r;  r<  r=  r>  r?  r@  rA  rH  ÚttlrR  rc   s   &$$$$$           r#   Ú_account_state_from_tokenrF    s  € ÷
 sÓrßlÑlÜ
�,Š,”sÓ
€CÙ
˜jŸn™n¨\¸1Ó=Ó
>€Cá˜:Ÿ>™>Ð*>Ó?Ó@÷ 	Dð 	DØ˜VÕ$×7Ñ7×>Ñ>¸sÓCð ð 	˜?Ð,@À-Ø�Y ¨¯©¸Ó)@×)IÐ)IÀEØ�j—n‘n \°8Ó<Ø˜
 >Õ2°OÀZÇ^Á^ÐTcÓEdØ�s—}‘}“¨±jÀÓ6JÈLÐZ]ØÑ% fÓ-ðOð 2NðO€Eñ *¨%ÀÐ`eÔf€EÜ/€Eˆ-ÑØ€Lr"   c               ó    € V ^8„  d   QhRRRR/# )r&   Úaccount_staterÔ   r*   r   )r+   s   "r#   r,   r,     s   € ÷ 2-ñ 2-¨ð 2-¸>ñ 2-r"   c                óÆ  € ^ RI Hp  V! 4       P                  R4      p\        T\        4      '       d   TM\        T\        4      '       d   RT/M/ p\        TP                  R4      ;'       g    R4      P                  4       pT\        8H  p\        TP                  R	4      4      pT'       g   T'       g   RTRR/# TpT'       d1   ^ R
IHp	  \        T	! 4       P                  R4      ;'       g    R4      p ^ RIHp
 T
! R\        T P                  R4      ;'       g    R4      T'       d   TMRT;'       d    T'       * R7       RTRR/#   \         d'   p\        P                  RT4       RRRR/u Rp?# Rp?ii ; i  \         d#   p\        P                  RT4       Rp Rp?L°Rp?ii ; i  \         d'   p\        P                  RT4       RTRR/u Rp?# Rp?ii ; i)aŒ  After a sign-in from the free tier persisted the account: move the config off the free tier's route.

Picking the free-tier row may have written ``model.default: nous/welcome`` and ``model.base_url``
= welcome host. An account cannot keep either: the welcome host refuses account tokens, and the
portal host serves ``nous/welcome`` as a paid model. When the config is on the free tier's route,
``model.base_url`` becomes the account's inference host and ``model.default`` the recommended
default for the account's tier (:func:`hermes_cli.models.recommended_nous_default_model`, the
same pick as ``GET /api/model/recommended-default``), through the same config write a plain Nous
login uses. A config on the user's own model and host is left alone.

Every sign-in completion (CLI ``hermes auth upgrade``, the desktop poller) calls this once, after
``persist_nous_credentials``. Returns ``{"model": str, "changed": bool}``: ``model`` is the default
the config now carries (``""`` when it carries none); ``changed`` says whether this call wrote it.
Never raises: a failed pick or write is logged and reported as ``changed: False`` so the sign-in
itself still counts.
rT   r±   zCsign-in completion: config unreadable, default model left as is: %srt   ÚchangedFNr  r°   )Úrecommended_nous_default_modelz7sign-in completion: recommended default unavailable: %sr  rV   r>  )r  Úclear_defaultz:sign-in completion: could not update the default model: %sT)rY   rU   rL   rZ   r[   Úwarningr]   r^   r(   r§   r�   r³   Úhermes_cli.modelsrK  r\   r}   r  )rH  rU   r«   r~   r   ÚcurrentÚon_welcome_modelÚon_welcome_hostr±   rK  r  s   &          r#   Úsettle_after_upgraderR    s­  € õ" 7ð/Ù"Ó$×(Ñ(¨Ó1ˆô " #¤t×,Ò,‘ÄzÐRUÔWZ×G[ÒG[°I¸sÑ3CÐac€IÜ�)—-‘- 	Ó*×0Ð0¨bÓ1×7Ñ7Ó9€GØ¤+Ñ-ÐÜ+¨I¯M©M¸*Ó,EÓF€Oß§Ø˜ )¨UÐ3Ð3Ø€EßÝDð	ÜÑ6Ó8×<Ñ<¸WÓE×KÐKÈÓLˆEð4Ý?ñ
 	$Ø”C˜×)Ñ)Ð*>Ó?×EÐEÀ2ÓFß#3™%¸Ø*×8Ð8°5¬yõ	:ð �U˜I tÐ,Ð,øô= ô /Ü�‰Ð\Ð^aÔbØ˜˜Y¨Ð.Õ.ûð/ûô ô 	Ü�L‰LÐRÐTWÔXØ�Eûð	ûô ô 4Ü�‰ÐSÐUXÔYØ˜ )¨UÐ3Õ3ûð4úsk   ˆE Ã!E? Ã0E? Ã8%F/ ÄF/ Ä,F/ Ä8F/ ÅE<ÅE7Å1E<Å7E<Å?F,Æ
F'Æ'F,Æ/G Æ:GÇG ÇG c               ó   € V ^8„  d   QhRR/# rå   r   )r+   s   "r#   r,   r,   N  s   € ÷ !ñ !¨ñ !r"   c                 ó   € ^ RI Hp V! V / VB # )zMKeep both the sign-in module seam and the device-flow seam live at call time.)Ú_poll_for_token)Úhermes_cli.auth_device_flowrU  )ÚargsÚkwargsÚpolls   *, r#   rU  rU  N  s   € åCÙ�Ð ˜Ñ Ð r"   c                 ó   € ^ RI Hp V! V / VB # )zLKeep the existing auth_nous persistence seam behind the sign-in entry point.)Úpersist_nous_credentials)rÿ   r[  )rW  rX  Úpersists   *, r#   r[  r[  T  s   € åHÙ�DÐ#˜FÑ#Ð#r"   )ÚAlreadySignedInÚ	CancelledÚCodeÚ	CompletedÚFREE_TIER_RATE_LIMIT_CARDÚFREE_TIER_RATE_LIMIT_CHATÚFailedÚLOGIN_BUSY_ELSEWHEREÚLOGIN_COMMANDÚLOGIN_DM_ONLYÚLOGIN_NOT_ALLOWEDÚLOGIN_STARTINGÚSignInStateÚTimedOutÚUPGRADE_ALREADY_SIGNED_INÚUPGRADE_CANCELLEDÚUPGRADE_DO_NOT_SHAREÚUPGRADE_NOT_COMPLETEDÚUPGRADE_NO_DEFAULT_CHATÚUPGRADE_NO_DEFAULT_TERMINALÚUPGRADE_STARTÚUPGRADE_TIMED_OUTÚUPGRADE_WAITINGÚUPGRADE_WAITING_UP_TOÚWaitingÚ_default_persist_guardÚformat_wait_lineÚrun_sign_in)Údrain_sign_in_copyÚrender_sign_in_cliÚrender_sign_in_cli_codeÚupgrade_guestr‚   )é”  Úunknown_token)r}  N)é‘  Úinvalid_shared_secret)r  N)r0  Úaccount_locked)r0  Úanonymous_accounts_disabled)r0  Úcircuit_openr/  )i­  N)i÷  Útemporarily_disabled)g      .@rl  g     Àr@>   rï  rñ  rÛ  rð  rÜ  ))zanonymous accounts must userÝ  )z+serves anonymous hermes agent accounts onlyrÞ  )z#anonymous accounts are not acceptedrß  )zinvalid jwtrà  )®Ú__conditional_annotations__r    Ú
__future__r   Úloggingr}  r£   rt  Údataclassesr   r   r   r   r   Úpathlibr   Útypingr	   r
   r   r   Úagent.retry_utilsr   rn   r   r   r   r   r   r   r   Ú	getLoggerr[   rf   ri  ro   r�   rË   rÅ   rì   ÚGUEST_MINT_TIMEOUT_SECONDSÚFREE_TIER_LABELÚUPGRADE_HINTÚFREE_TIER_NOT_SIGNED_INr   r1   ÚANON_GATE_CLOSEDr®  ÚANON_RATE_LIMITEDrÞ   ÚANON_ACCOUNT_LOCKEDrÏ  r¡  rM   ÚANON_CHALLENGE_REQUIREDÚANON_SIGNIN_REQUIREDrª   r0   ÚANON_UNREACHABLE_CODESÚ_SIGNIN_IS_FREErK   rG   rO   r`   rh   rp   rv   r   rƒ   r‰   rŒ   r‘   r”   r—   rž   r©   r¥   r®   r¶   r¹   r³   rÂ   rÆ   rÎ   rÏ   r�  r^   r(   Ú_Verdictrã   rí   rù   r  r  r6  rT  rY  r\  rk  r«  r¯  rn  r‚  r‰  rŒ  r�  r”  r˜  r¥  r²  rÂ  rÉ  rÐ  rÚ  r  rå  ÚWELCOME_TIER_GATE_REASONSrÿ  r  rò  ró  r  r  ÚFREE_TIER_OUTAGE_COPYré  r÷  r   r  r  r!  r%  r&  r*  r)  r/  rD  rF  rR  rU  r[  Úhermes_cli.anon_sign_inr]  r^  r_  r`  ra  rb  rc  rd  re  rf  rg  rh  ri  rj  rk  rl  rm  rn  ro  rp  rq  rr  rs  rt  ru  rv  rw  rx  Úhermes_cli.anon_sign_in_cliry  rz  r{  r|  )r…  s   @r#   Ú<module>r�     sä  øðôõ6 #ã Û Û 	Û Ý !ß 7Ó 7Ý ß 0Ó 0å 7÷÷ ñ ð 
×	Ò	Ð,Ó	-€àÐ Ø €ØÐ Ø€Ø-Ð ð +€ð
 ?Ð Ø Ð à%€Øc€ð8ð ô
˜ô ðmÈ÷ mð, &Ð Ø%Ð Ø'Ð Ø'Ð Ø+Ð Ø-Ð Ø%Ð Ø'Ð Ø3Ð Ø-Ð áØÐ'Ð)<Ð>Rð!Tó UÐ ñ #Ð$4Ð6GÐ#HÓIÐ ð (€àÐKÈOÐK\Ð]ØÐPÐQ`ÐPaÐbØð @àð MàÐVØÐlØÐKÈOÐK\Ð]ØÐLØÐkØÐNðÐ õ Eð"S°t÷ Sõ
-õTõgõaõ
õ0õ&÷_õ:õ#õFõJñ
 Ð9Ð:Ó;€ð
 7Ð õHõ
õ-õ#õIõ
;õð Ð/Ð1EÐFØ�)Ð-Ð.Ø" YÐ0@Ð$AØÐ$Ð&:Ð;ØÐ0Ð2EÐFØ(¨9Ð6FÐ*GØ˜IÐ'7Ð8Ø�)Ð.Ð/Ø�)Ð.Ð/Ø! IÐ/?Ð#@ð%€Ð!ó ð �T˜#˜s˜(•^Ð$ iÐ/Õ0€ð9Ø[_÷9õ:kõ	õ"FðKÀt÷ Kõ&õR %õFPõ
\õð> )Ð ØÐ ð ÷Uð Uó ðUð, *,€Ð&Ó +õKõ
0õ/õõ5õõ"ð(-#Àeð -#Ø38÷-#ð`0Ø0Jð0ØZ_ð0à÷0õf%ð0aÀ÷ aðP ,Ð á#Ú]ó_Ð ñ &Ð'7Ð9KÐ&LÓMÐ ðÐ ð ð PàÐQØð Eð ð cðÐ ð %€Ø7Ð Ø<Ð ØHÐ ðGÐ õPð.bÀ"ð bÐVZð bÐim÷ b÷<ð*S¸Tð SÐPT÷ Sõõ<'ðZ )Ð õSõ9õõ	@ð$ +Ð õõ02-õj!ò$÷÷ ÷ ÷ ÷ ÷ ÷ ó ÷<õ r"   