+
    jHàjßZ  ã                  óŒ  a € 0 t $ R t^ RIHt ^ RIt^ RIt^ RIt^ RIt^ RIt^ RI	t	^ RI
t
^ RIt^ RIHtHtHt ^ RIHtHtHtHtHt ^ RIHt ^ RIHtHtHtHtHt ^ RIHtH t  ]PB                  ! R4      t"R	t#R
t$Rt%RRut&t'RRRut(t)t*Rt+Rt,Rt-]! R4      t.]! RR7       ! R R4      4       t/ ! R R]4      t0R\R R llt1R R lt2R R lt3R  R! lt4R" R# lt5R$ R% lt6R& R' lt7R( R) lt8R* R+ lt9] ! R, R-4      4       t:]
Pv                  ! 4       t</ t=R.]>R/&   ]?! 4       t@R0]>R1&   ]P‚                  ! R2R3R47      tBR5]>R6&   ]P†                  R7 4       tDR8 R9 ltER: R; ltFR< R= ltGR> R? ltHR@ RA ltIRB RC ltJRD RE ltKRF RG ltLRH RI ltMRJ RK ltNRL RM ltORN RO ltPRP RQ ltQRR RS ltRR]tS]P¨                  tURT RU ltVRV RW ltWRX RY ltXRZ R[ ltYR# )^a³  Nous free tier: the browser challenge the account service may put in front of a token exchange.

NAS can answer ``POST /api/anonymous/token`` with **428** ``challenge_required`` and a list of
challenges. Hermes implements exactly one primitive, ``browser-v1``: *open this portal URL, poll
until it clears, exchange again*. Everything the page does (bot detection, an in-browser proof of
work, an interactive fallback, its copy) belongs to the portal and changes without a Hermes release.

Who opens the URL depends on the surface:

* **desktop** (``HERMES_DESKTOP=1``): this process never opens anything. It publishes the challenge
  (``free_tier.challenge`` global event, and ``free_tier.status``'s ``challenge`` field for a client
  that connects later); the renderer hands it to the Electron main process, which loads it in a
  HIDDEN window and reveals that window only if the page asks for the human.
* **terminal**: print the URL, and open the system browser when there is a graphical one to open.

The wait runs OUTSIDE the auth-store and shared-store locks: the exchange that hit the 428 has
already unwound (the exception left the ``with`` blocks), so a slow page never stalls a sibling
profile or process. One challenge is worked at a time per process; a second thread that hits the
same 428 waits for the first and then simply exchanges again (NAS hands a retried mint the same
ticket, and a cleared credential a token).

Only a caller someone is waiting on waits for a challenge. A background reader (the keepalive tick,
a status paint) runs inside :func:`background_caller`: it still gets the challenge in front of a
desktop client (so the hidden window can clear it before anyone needs a token) but never blocks,
prints, or opens a browser.

An *optional* challenge (``required: false`` on a successful exchange: the service is measuring, not
enforcing) is only ever announced to a desktop client, never opened in a user's browser, and
nothing waits on it.
)ÚannotationsN)Ú	dataclassÚfieldÚreplace)ÚAnyÚCallableÚDictÚOptionalÚTypeVar)Úurlparse)ÚANON_CHALLENGE_REQUIREDÚANON_FAILURE_COPYÚANON_SIGNIN_REQUIREDÚ_anon_headersÚ_mint_memo_key)Ú	AuthErrorÚhttpxzhermes_cli.authz
browser-v1zfree_tier.challengeg      ^@g      ð?g      @g      >@g      Œ@g     À‚@i,  zBNous needs to run a quick check before starting your free session.ÚTT)Úfrozenc                  ód   € ] tR t^Ht$ R]R&   R]R&   R]R&   R]R&   R]R&   ^ tR	]R
&   R R ltRtR# )ÚBrowserChallengeÚstrÚurlÚboolÚrequiredÚfloatÚ
expires_inÚintervalÚmessageÚintÚattemptc               ó   € V ^8„  d   QhRR/# ©é   Úreturnúdict[str, Any]© )Úformats   "Ú>/home/ubuntu/.hermes/hermes-agent/hermes_cli/anon_challenge.pyÚ__annotate__ÚBrowserChallenge.__annotate__Q   s   € ÷ fñ f˜Nñ fó    c                	ó”   € R RRV P                   RV P                  R\        V P                  4      RV P                  RV P
                  /# )ÚtypeÚbrowserr   r   r   r   r    )r   r   r   r   r   r    )Úselfs   &r(   Ú
as_payloadÚBrowserChallenge.as_payloadQ   sD   € Ø˜	 5¨$¯(©(°JÀÇÁØœc $§/¡/Ó2°I¸t¿|¹|ÈYÐX\×XdÑXdðfð 	fr+   r&   N)Ú__name__Ú
__module__Ú__qualname__Ú__firstlineno__Ú__annotations__r    r0   Ú__static_attributes__r&   r+   r(   r   r   H   s2   ‡ à	ƒHØƒNØÓØƒOØƒLØ€GˆSÓ÷fñ fr+   r   c                  ó2   a € ] tR t^VtRtR V 3R lltRtV ;t# )ÚAnonChallengeRequiredzÂThe exchange needs a browser challenge first. Carries what :func:`run_with_challenge` needs
to work it: the challenge, and the portal, credential and auth state (its ``tls`` block) to poll with.c          
     ó,   € V ^8„  d   QhRRRRRRRRRR	/# )
r#   Ú	challenger   Úportal_base_urlr   Ú
anon_tokenÚ
auth_stater%   r$   ÚNoner&   )r'   s   "r(   r)   Ú"AnonChallengeRequired.__annotate__Z   s3   € ÷ %ñ %Ð"2ð %Èð %ÐY\ð %Ø+ð%Ø04ñ%r+   c               	óz   <€ \         SV `  VP                  R \        RR7       Wn        W n        W0n        W@n        R# )ÚnousT©ÚproviderÚcodeÚ	retryableN)ÚsuperÚ__init__r   r   r;   r<   r=   r>   )r/   r;   r<   r=   r>   Ú	__class__s   &&$$$€r(   rH   ÚAnonChallengeRequired.__init__Z   s6   ø€ ä‰Ñ˜×*Ñ*°VÔBYÐeiÐÔjØ"ŒØ.ÔØ$ŒØ$Žr+   )r=   r>   r;   r<   )r2   r3   r4   r5   Ú__doc__rH   r7   Ú__classcell__)rI   s   @r(   r9   r9   V   s   ø† ñn÷%ö %r+   r9   c               ó    € V ^8„  d   QhRRRR/# )r#   r   r   r$   r   r&   )r'   s   "r(   r)   r)   c   s   € ÷ Añ A 3ð A°)ñ Ar+   c                ól   € \        \        V 4      ;'       g    \        \        ,          R\        RR7      # )z˜The service will not serve this client without an account (or asked for something this
version cannot do). Terminal for the process, like a closed gate.rB   FrC   )r   Úserver_messager   r   )r   s   &r(   Úsignin_required_errorrP   c   s1   € ô ”^ GÓ,×WÐWÔ0AÔBVÕ0WÐbhÜ.¸%ôAð Ar+   c               ó    € V ^8„  d   QhRRRR/# )r#   Úvaluer   r$   r   r&   )r'   s   "r(   r)   r)   j   s   € ÷ ?ñ ?˜#ð ? #ñ ?r+   c                óÞ   € \        V \        4      '       g   R# RP                  RP                  R V  4       4      P                  4       4      p^ \	        V4      u;8  d   \
        8:  d   V#  R# )zUUser-facing copy the service sent, if it is plausibly that: a short single paragraph.Ú Ú c              3  óT   "  € T F  qP                  4       '       d   TMR x € K   	  R# 5i)rU   N)Úisprintable)Ú.0Úchs   & r(   Ú	<genexpr>Ú!server_message.<locals>.<genexpr>p   s   é € ÐLÁeÀ§.¡.×"2Ò"2™B¸Ô;Ãeùs   ‚&()Ú
isinstancer   ÚjoinÚsplitÚlenÚ_MESSAGE_MAX_CHARS)rR   Útexts   & r(   rO   rO   j   sY   € ä�eœS×!Ò!Ùð �8‰8�B—G‘GÑLÁeÓLÓL×RÑRÓTÓU€DØ”s˜4“yÖ6Ô$6Ô6ˆ4Ð>Ð6¸BÐ>r+   c               ó   € V ^8„  d   QhRR/# ©r#   r$   r   r&   )r'   s   "r(   r)   r)   w   s   € ÷ >ñ >˜ñ >r+   c                 óÈ   € ^ RI Hp Hp V! 4       '       d   R# \        P                  P                  R4      pVe   VP                  4       '       d   R# V ! 4       '       d   R# R# )aV  ``gateway`` in the process that holds the messaging gateway's runtime lock (nobody is at its
console) unless it is serving the local Desktop app, ``desktop`` for that and for the backend the
desktop app spawned, else ``cli``. ``HERMES_DESKTOP``
alone is inherited by every terminal-pane shell, so desktop ownership needs the spawn credential.)Úis_desktop_owned_backendÚserves_local_desktop_nowÚdesktopzgateway.statusÚgatewayÚcli)Úhermes_cli.process_identityre   rf   ÚsysÚmodulesÚgetÚowns_gateway_runtime_lock)re   rf   Ústatuss      r(   Úclient_surfacerp   w   sQ   € ÷
 _Ù×!Ò!ÙÜ�[‰[�_‰_Ð-Ó.€FØÒ˜f×>Ñ>×@Ò@ÙÙ0×2Ò2ˆ9Ð=¸Ð=r+   c               ó   € V ^8„  d   QhRR/# r"   r&   )r'   s   "r(   r)   r)   …   s   € ÷ Lñ L�^ñ Lr+   c            
     óz   € ^ RI Hp  RRRV ! 4       P                  R\        4       R\        P
                  R\        ./# )z²The self-reported ``client`` block on a token exchange. It sorts honest clients (which
surface, which challenge primitives) for the service's rules; it proves nothing, by design.©Úget_version_infoÚnamezhermes-agentÚversionÚsurfaceÚplatformÚcapabilities)Úhermes_cli.version_infort   Úbase_versionrp   rk   rx   ÚBROWSER_CAPABILITYrs   s    r(   Úclient_infor}   …   s@   € õ 9Ø�N IÑ/?Ó/A×/NÑ/NÐPYÔ[iÓ[kØœŸ™ nÔ7IÐ6JðLð Lr+   c               ó   € V ^8„  d   QhRR/# rc   r&   )r'   s   "r(   r)   r)   �   s   € ÷ Xñ X�Cñ Xr+   c            	     ó°   € ^ RI Hp  RV ! 4       P                   R\        4        R\        P
                   R\
        P                  ! 4       ;'       g    R R2	# )é    rs   zhermes-agent/z (z; ÚunknownÚ))rz   rt   r{   rp   rk   rx   Úmachiners   s    r(   Ú
user_agentr„   �   sV   € Ý8ØÑ,Ó.×;Ñ;Ð<ð =ÜÓ Ð! ¤C§L¡L >°´H×4DÒ4DÓ4F×4SÐ4SÈ)Ð3TÐTUðWð Xr+   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&   € ÷ Xñ X�cð X¨Cð X°Dñ Xr+   c                óf  €  \        V 4      \        V4      r2TP                  R9   ;'       dt    TP                  TP                  8H  ;'       dS    \        TP                  4      ;'       d6    TP                  P                  4       TP                  P                  4       8H  #   \         d     R# i ; i)z¡A challenge URL is only ever opened on the portal the exchange itself went to: the response
is network input, and "open this URL" must not become "open any URL".F)ÚhttpsÚhttp)r   Ú
ValueErrorÚschemer   ÚnetlocÚlower)r   r<   ÚtargetÚportals   &&  r(   Ú_same_originr�   –   s¡   € ðÜ! #›¬°Ó(A�ð �M‰MÐ.Ñ.÷ Wð W°6·=±=ÀFÇMÁMÑ3Q÷ Wð WÜ�V—]‘]Ó#÷Wð WØ(.¯©×(;Ñ(;Ó(=ÀÇÁ×ATÑATÓAVÑ(VðXøô ô Úðús   ‚B! Â!B0Â/B0c               ó$   € V ^8„  d   QhRRRRRR/# )r#   rR   r   Údefaultr   r$   r&   )r'   s   "r(   r)   r)   ¡   s!   € ÷ ñ �3ð  ð ¨5ñ r+   c                ó¸   € \        V \        4      '       g9   \        V \        \        34      '       d   \        P
                  ! V 4      '       g   V# \        V 4      # ©N)r\   r   r   r   ÚmathÚisfinite)rR   r‘   s   &&r(   Ú_numberr–   ¡   s=   € Ü�%œ×Ò¤j°¼¼e¸×&EÒ&EÌTÏ]Ê]Ð[`×MaÒMaØˆÜ�‹<Ðr+   c               ó$   € V ^8„  d   QhRRRRRR/# )r#   Úpayloadr%   r<   r   r$   úOptional[BrowserChallenge]r&   )r'   s   "r(   r)   r)   §   s"   € ÷ ñ  ^ð Àcð ÐNhñ r+   c                óþ  € V P                  R4      p\        V\        4      '       g   R# \        V P                  R4      4      ;'       g    \        pV EF$  p\        V\
        4      '       d   VP                  R4      R8w  d   K2  VP                  R4      p\        V\        4      '       d(   VP                  4       '       d   \        WQ4      '       g   \        P                  R4       K—  \        WTP                  R4      R	J\        \        \        \        \!        VP                  R
4      \"        4      4      4      \        \$        \        \&        \!        VP                  R4      R4      4      4      VR7      u # 	  R# )zNThe first challenge in ``payload["challenges"]`` this client can run, or None.Ú
challengesNr   r-   r.   r   zBNous free tier: ignoring a challenge URL outside the portal originr   Fr   r   g       @)r   r   r   r   r   )rm   r\   ÚlistrO   ÚCHALLENGE_COPYÚdictr   rW   r�   ÚloggerÚinfor   ÚminÚ_EXPIRES_MAX_SECONDSÚmaxÚ_EXPIRES_MIN_SECONDSr–   Ú_EXPIRES_DEFAULT_SECONDSÚ_POLL_MAX_SECONDSÚ_POLL_MIN_SECONDS)r˜   r<   Úentriesr   Úentryr   s   &&    r(   Úparse_browser_challengerª   §   s  € à�k‰k˜,Ó'€GÜ�gœt×$Ò$ÙÜ˜WŸ[™[¨Ó3Ó4×FÐF¼€GÜˆÜ˜%¤×&Ò&¨%¯)©)°FÓ*;¸yÔ*HÙØ�i‰i˜ÓˆÜ˜#œs×#Ò#¨3¯?©?×+<Ò+<ÄLÐQT×DfÒDfÜ�K‰KÐ\Ô]ÙÜØŸi™i¨
Ó3¸5Ð@ÜÔ/´Ü$¤g¨e¯i©i¸Ó.EÔG_Ó&`ó2bó cäÔ*¬CÔ0AÄ7È5Ï9É9ÐU_ÓK`ÐbeÓCfÓ,gÓhØôò 	ñ ñ r+   c          
     ó,   € V ^8„  d   QhRRRRRRRRRR/# )	r#   r˜   r%   r<   r   r=   r>   r$   r   r&   )r'   s   "r(   r)   r)   ½   s2   € ÷ 	8ñ 	8˜^ð 	8Àð 	8ÐRUð 	8Ø .ð	8Ø3<ñ	8r+   c               óP   € \        W4      pVf   \        4       # \        WAVVR7      # )z…The error for a 428 ``challenge_required``: a challenge to work, or (nothing offered that
this version can run) the sign-in fallback.)r<   r=   r>   )rª   rP   r9   )r˜   r<   r=   r>   r;   s   &$$$ r(   Úchallenge_errorr­   ½   s2   € ô (¨ÓA€IØÒä$Ó&Ð&Ü  ÐXbØ,6ô8ð 8r+   c                  ó„   € ] tR t^Ìt$ Rt]! ]P                  R7      tR]	R&   Rt
R]	R&   RtR	]	R
&   RtR]	R&   RtR	]	R&   RtR# )Ú_ProfileChallengez–One profile's challenge state, behind ``_state_lock``. ``work_lock`` serialises waits PER
PROFILE (a sibling profile's wait must not queue behind it).)Údefault_factoryzthreading.LockÚ	work_lockNr™   Úpendingg        r   ÚdeadlineúOptional[str]ÚoutcomeÚgave_up_untilr&   )r2   r3   r4   r5   rK   r   Ú	threadingÚLockr±   r6   r²   r³   rµ   r¶   r7   r&   r+   r(   r¯   r¯   Ì   sD   ‡ ñDá %°i·n±nÔ E€Iˆ~ÓEØ*.€GÐ'Ó.Ø€HˆeÓØ!€Gˆ]Ó!Ø€M�5×r+   r¯   zdict[str, _ProfileChallenge]Ú	_profileszset[str]Ú_opened_urlsÚanon_challenge_backgroundF)r‘   zcontextvars.ContextVar[bool]Ú_backgroundc               #  ó    "  € \         P                  R4      p  Rx € \         P                  V 4       R#   \         P                  T 4       i ; i5i)zªMark the enclosed token reads as background work (a keepalive tick, a status paint): a
challenge is announced to a desktop client but never waited on, printed, or opened.TN)r¼   ÚsetÚreset)Útokens    r(   Úbackground_callerrÁ   ß   s9   é € ô �O‰O˜DÓ!€Eð!Ûä×Ñ˜%Ö øŒ×Ñ˜%Õ üs   ‚A™4 �A´AÁAc               ó   € V ^8„  d   QhRR/# )r#   r$   r¯   r&   )r'   s   "r(   r)   r)   ê   s   € ÷ Kñ KÐ#ñ Kr+   c                 ó¨   € \         ;_uu_ 4        \        P                  \        4       \	        4       4      uuRRR4       #   + '       g   i     R# ; i)zSThis profile's record. Callers hold ``_state_lock`` for anything but ``work_lock``.N)Ú_state_lockr¹   Ú
setdefaultr   r¯   r&   r+   r(   Ú_profilerÆ   ê   s*   € ç	ŽÜ×#Ñ#¤NÓ$4Ô6GÓ6IÓJ÷ 
��‹ús   �&A Á A	c               ó    € V ^8„  d   QhRRRR/# )r#   Úrecordr¯   r$   r™   r&   )r'   s   "r(   r)   r)   ð   s   € ÷ ñ Ð#ð Ð(Bñ r+   c                ó¤   € V P                   '       d4   V P                  \        P                  ! 4       8:  d   R R uV n         V n        V P                   # r“   )r²   r³   ÚtimeÚ	monotonicrµ   ©rÈ   s   &r(   Ú_liverÍ   ð   s7   € Ø‡~‡~€~˜&Ÿ/™/¬T¯^ª^Ó-=Ô=Ø)-¨tÐ&ˆŒ˜œØ�>‰>Ðr+   c               ó   € V ^8„  d   QhRR/# )r#   r$   zOptional[dict[str, Any]]r&   )r'   s   "r(   r)   r)   ö   s   € ÷ 	gñ 	gÐ3ñ 	gr+   c            	     ób  € \        4       p \        ;_uu_ 4        \        V 4      pVe   V P                  R9  d    RRR4       R# / VP	                  4       CR\
        P                  ! V P                  \        P                  ! 4       ,
          4      /CuuRRR4       #   + '       g   i     R# ; i)a  The challenge this profile is waiting on, for ``free_tier.status`` (a client that connected
after the event fired still learns it has a window to open). None once cleared or expired, or
once the host said how its window ended (a window the user closed must not come back).Nr   )NÚtimeoutÚerror)
rÆ   rÄ   rÍ   rµ   r0   r”   Úceilr³   rÊ   rË   )rÈ   r;   s     r(   Úpending_challengerÓ   ö   sx   € ô ‹Z€Fß	ŽÜ˜&“Mˆ	ØÒ §¡Ð6PÔ PØ÷ 
‰ð g�)×&Ñ&Ó(Ðf¨,¼¿	º	À&Ç/Á/ÔTX×TbÒTbÓTdÕBdÓ8eÑf÷	 
��‹ús   ™"BÁABÂB.	c               ó   € V ^8„  d   QhRR/# ©r#   r$   r?   r&   )r'   s   "r(   r)   r)     s   € ÷ 4ñ 4˜ñ 4r+   c                 óŽ   € \        4       p \        ;_uu_ 4        R R uV n        V n        R R R 4       R #   + '       g   i     R # ; ir“   )rÆ   rÄ   r²   rµ   rÌ   s    r(   Ú_clear_pendingr×     s*   € Ü‹Z€Fß	ŽØ)-¨tÐ&ˆŒ˜œ÷ 
��Šús	   ™3³A	c               ó$   € V ^8„  d   QhRRRRRR/# )r#   r;   r   Únew_attemptr   r$   r&   )r'   s   "r(   r)   r)     s#   € ÷ ñ Ð'ð ¸ð ÐBRñ r+   c               ó0  € \        4       p\        ;_uu_ 4        \        V4      p\        P                  ! 4       V P
                  ,           pVe   VP                  V P                  8w  d#   \        V ^ R7      VRuVn        Vn	        Vn
        MbV'       d   VP                  ^,           MVP                  p\        WR7      \        WBP                  4      uVn        Vn	        V'       d   RVn
        VP                  uuRRR4       #   + '       g   i     R# ; i)a  Record *challenge* as the profile's pending one. A replay of the same ticket (a background
read, a second 428) keeps the original deadline, attempt and host outcome; ``new_attempt`` (a
foreground caller about to wait) bumps the attempt, which lets it reopen a window the user closed.N)r    )rÆ   rÄ   rÍ   rÊ   rË   r   r   r   r²   r³   rµ   r    r¡   )r;   rÙ   rÈ   Úpreviousr³   r    s   &$    r(   Ú_recordrÜ     s¾   € ô ‹Z€Fß	ŽÜ˜“=ˆÜ—>’>Ó# i×&:Ñ&:Õ:ˆØÒ˜xŸ|™|¨y¯}©}Ô<Ü>EÀiÐYZÔ>[Ð]eÐgkÐ;ˆFŒN˜FœO¨V­^ç.9�h×&Ñ&¨Ö*¸x×?OÑ?OˆGÜ.5°iÔ.QÔSVÐW_×apÑapÓSqÐ+ˆFŒN˜FœOßØ!%�”Ø�~‰~÷ 
��‹ús   ™A:DÂA%DÄD	c               ó(   € V ^8„  d   QhRRRRRRRR/# )r#   r   r   r    r   rµ   r$   r   r&   )r'   s   "r(   r)   r)     s(   € ÷ 	ñ 	˜Sð 	¨3ð 	¸ð 	Àñ 	r+   c                óî   € \        4       p\        ;_uu_ 4        \        V4      pVe   VP                  VP                  3W38w  d    RRR4       R# W#n         RRR4       R#   + '       g   i     R# ; i)z¡A presentation hint: wakes a waiter to re-mint, never grants clearance locally. A late
reply belongs to the attempt that opened the window, not to a newer retry.NFT)rÆ   rÄ   rÍ   r   r    rµ   )r   r    rµ   rÈ   r;   s   &&&  r(   Úrecord_host_outcomerß     sW   € ô ‹Z€Fß	ŽÜ˜&“Mˆ	ØÒ §¡°	×0AÑ0AÐ BÀsÀnÔ TØ÷ 
‰ð !ŒØ÷ 
��Šús   ™/A#ÁA#Á#A4	c               ó    € V ^8„  d   QhRRRR/# )r#   r;   r   r$   r´   r&   )r'   s   "r(   r)   r)   &  s   € ÷ 3ñ 3Ð-ð 3°-ñ 3r+   c                ó.  € \        4       p\        ;_uu_ 4        VP                  pVR J;'       d2    VP                  VP                  3V P                  V P                  38H  pV'       d   VP
                  MR uuR R R 4       #   + '       g   i     R # ; ir“   )rÆ   rÄ   r²   r   r    rµ   )r;   rÈ   r²   Úmatchess   &   r(   Ú_host_outcomerã   &  sb   € Ü‹Z€Fß	ŽØ—.‘.ˆØ Ð%×nÐn¨7¯;©;¸¿¹Ð*HÈYÏ]É]Ð\e×\mÑ\mÐLnÑ*nˆß!(ˆv�~Š~¨d÷ 
��‹ús   ™ABÁ+BÂB	c               ó   € V ^8„  d   QhRR/# rÕ   r&   )r'   s   "r(   r)   r)   .  s   € ÷ Lñ L�$ñ Lr+   c                 óº   € \        4       p \        ;_uu_ 4        \        P                  ! 4       \        ,           V n        R R R 4       R #   + '       g   i     R # ; ir“   )rÆ   rÄ   rÊ   rË   Ú_GAVE_UP_COOLDOWN_SECONDSr¶   rÌ   s    r(   Ú_give_uprç   .  s/   € Ü‹Z€Fß	ŽÜ#Ÿ~š~Ó/Ô2KÕKˆÔ÷ 
��Šús   ™&A	Á	A	c               ó   € V ^8„  d   QhRR/# )r#   r$   r   r&   )r'   s   "r(   r)   r)   4  s   € ÷ 7ñ 7˜4ñ 7r+   c                 ó´   € \        4       p \        ;_uu_ 4        \        P                  ! 4       V P                  8  uuR R R 4       #   + '       g   i     R # ; ir“   )rÆ   rÄ   rÊ   rË   r¶   rÌ   s    r(   Ú_gave_up_recentlyrê   4  s/   € Ü‹Z€Fß	ŽÜ�~Š~Ó &×"6Ñ"6Ñ6÷ 
��‹ús   ™"AÁA	c               ó   € V ^8„  d   QhRR/# rÕ   r&   )r'   s   "r(   r)   r)   :  s   € ÷ ñ ˜ñ r+   c                 ó¬   € \         ;_uu_ 4        \        P                  4        \        P                  4        R R R 4       R #   + '       g   i     R # ; ir“   )rÄ   r¹   Úclearrº   r&   r+   r(   Úreset_for_testsrî   :  s)   € ß	ŽÜ�‰ÔÜ×ÑÔ÷ 
��Šús   �)AÁA	c               ó    € V ^8„  d   QhRRRR/# )r#   r;   r   r$   r   r&   )r'   s   "r(   r)   r)   C  s   € ÷ ñ Ð)ð ¨dñ r+   c                ó  € \         P                  P                  R4      pVf   R#  VP                  \        V P                  4       4       R#   \        \        3 d'   p\        P                  R\        T4        Rp?R# Rp?ii ; i)a
  Broadcast to connected desktop clients. False when this process is not a gateway at all
(``HERMES_DESKTOP`` is an env var, and a CLI the desktop spawned inherits it): importing the
gateway here just to find nobody listening would also write an event frame to stdout.útui_gateway.serverNFz%s not broadcast: %sT)
rk   rl   rm   Ú_broadcast_global_eventÚCHALLENGE_EVENTr0   ÚOSErrorr‰   rŸ   Údebug)r;   ÚserverÚexcs   &  r(   Ú	_announcerø   C  so   € ô �[‰[�_‰_Ð1Ó2€FØ‚~ÙðØ×&Ñ&¤¸	×8LÑ8LÓ8NÔOñ øô ”ZÐ ô ô 	�‰Ð+¬_¸cÔBÝûð	ús   §$A ÁBÁA?Á?Bc               ó    € V ^8„  d   QhRRRR/# ©r#   r;   r   r$   r?   r&   )r'   s   "r(   r)   r)   T  s   € ÷ cñ cÐ$4ð c¸ñ cr+   c                ó°  € ^ RI HpHp RpV P                  \        9   pV'       gz   \        4       R8w  dk   V! 4       '       g^   V! 4       '       dQ   ^ RIp \        VP                  V P                  4      4      pV'       d    \        P                  V P                  4       \        RV P                   2\         P"                  R7       \        RV P                   2\         P"                  R7       \        V'       g	   V'       d   R	MR
\         P"                  R7       R#   TP                  \        3 d!   p\        P                  RT4        Rp?LØRp?ii ; i)r€   )Ú_can_open_graphical_browserÚ_is_remote_sessionFrh   Nz-could not open the challenge in a browser: %sÚ
©Úfilez  Open: z  (Opened in your browser.)
z>  (Open that link in any browser; this continues on its own.)
)Úhermes_cli.auth_device_flowrü   rý   r   rº   rp   Ú
webbrowserr   ÚopenÚErrorrô   rŸ   rõ   ÚaddÚprintr   rk   Ústderr)r;   rü   rý   ÚopenedÚalready_openr  r÷   s   &      r(   Ú_present_in_terminalr
  T  sò   € ß[Ø€Fð —=‘=¤LÑ0€Lßœ^Ó-°Ô:Ù&×(Ò(Ñ-H×-JÒ-JÛð	OÜ˜*Ÿ/™/¨)¯-©-Ó8Ó9ˆF÷ Ü×Ñ˜YŸ]™]Ô+Ü	ˆBˆy× Ñ Ð!Ð
"¬¯©Õ4Ü	ˆH�Y—]‘]�OÐ
$¬3¯:©:Õ6Ü	¯V·|Ñ
)ØPÔWZ×WaÑWa÷cøð × Ñ ¤'Ð*ô 	OÜ�L‰LÐHÈ#×NÑNûð	Oús   Á$D ÄEÄ5EÅEc               ó    € V ^8„  d   QhRRRR/# rú   r&   )r'   s   "r(   r)   r)   i  s   € ÷ $ñ $Ð'ð $¨Dñ $r+   c                óL  € \        4       R8X  d   \        V 4      '       d   R# V P                  '       d   \        P	                  4       '       d   R# \
        P                  P	                  R4      pVe&   VP                  '       d   \        V 4      '       d   R# \        V 4       R# )aL  Get the URL in front of something that can load it.

The desktop backend hands every challenge to its hidden window. The stdio TUI gateway (whose
stderr the TUI keeps as a log, never shows) hands its client a required one a foreground caller
is waiting on: a background read there must not pop a browser any more than in a terminal.rg   Nrñ   )	rp   rø   r   r¼   rm   rk   rl   Ú_stdio_is_rpc_channelr
  )r;   rö   s   & r(   Úpresentr  i  sp   € ô Ó˜9Ô$¬°9×)=Ò)=ÙØ××Ð¤§¡×!2Ò!2ÙÜ�[‰[�_‰_Ð1Ó2€FØÒ˜f×:×:Ð:¼yÈ×?SÒ?SÙÜ˜Ö#r+   c               ó(   € V ^8„  d   QhRRRRRRRR/# )r#   Úclientzhttpx.Clientr<   r   r=   r$   r&   )r'   s   "r(   r)   r)   |  s)   € ÷ <ñ <˜ð <¸ð <Èð <ÐQTñ <r+   c                ó  €  V P                  VP                  R4       R2\        4       RV/R7      pRVP                  u;8:  d   R8  d   M MVP                  R8w  d   R# VP                  ^È8X  d   VP	                  4       MR	p\        V\        4      '       d   VP                  R4      MR	p\        V\        4      '       d   V# R#   \
        P                  \        3 d#   p\        P                  R
T4       R	p R	p?L{R	p?ii ; i)zóOne status read. Anything that is not a clear ``pending`` / ``needs_interaction`` ends the
wait: the exchange that follows is the authority on whether the credential is cleared. (A
passed challenge reads ``none``: passing detaches the ticket.)Ú/z/api/anonymous/challenge/statusrÀ   )ÚheadersÚjsoni�  iô  i­  ÚnoneNz challenge status poll failed: %sro   r²   )ÚpostÚrstripr   Ústatus_coder  r   Ú	HTTPErrorr‰   rŸ   rõ   r\   rž   rm   r   )r  r<   r=   ÚresponseÚbodyr÷   ro   s   &&&    r(   Ú_poll_statusr  |  sâ   € ð
Ø—;‘; /×"8Ñ"8¸Ó"=Ð!>Ð>]Ð^Ü'4£¸gÀzÐ=Rð ó Tˆà�(×&Ñ&Ö,¨×,°×1EÑ1EÈÔ1Lñ Ø"*×"6Ñ"6¸#Ô"=ˆx�}‰}ŒÀ4ˆô $.¨d´D×#9Ò#9ˆT�X‰X�hÔ¸t€Fô   ¬×,Ò,ˆ6Ð;°)Ð;øô �O‰OœZÐ(ô Ü�‰Ð7¸Ô=Ø�ûðús   ‚AC Á!#C ÃDÃ"C?Ã?Dc               ó    € V ^8„  d   QhRRRR/# )r#   r÷   r9   r$   r   r&   )r'   s   "r(   r)   r)   •  s   € ÷ !ñ !Ð1ð !°dñ !r+   c                ó€  € ^ RI Hp ^ RIHp \	        4       '       d   R# V P
                  p\        P                  ! 4       \        \        VP                  4      ,           pV! V P                  R7      pRpV! RV4      ;_uu_ 4       p\        WpP                  V P                  4      \        9  d    RRR4       R# \!        VRR7      ;q0n        \#        V4       \        P                  ! 4       V8  d§   \%        V4      e    RRR4       R# \'        VP(                  4       \        WpP                  V P                  4      pV\        9  d    RRR4       R# VR	8X  g   K†  V'       d   K�  Rp\+        4       R
8w  g   K£  \-        R\.        P0                  R7       KÀ   RRR4       \3        4        R#   + '       g   i     L; i)aW  Present *exc*'s challenge and poll until status or a host hint ends the wait.
True = a result arrived; False = patience ran out. Re-mint is authoritative in either case.

Called under the profile's work lock. A caller that queued behind another finds the ticket
already settled on its first status read and returns without presenting anything.)Ú_resolve_verify)Ú_nous_http_clientF)r>   g      $@NT©rÙ   Úneeds_interactionrg   z5  Finish the quick check in your browser to continue.rÿ   )Úhermes_cli.authr  Úhermes_cli.auth_nousr   rê   r;   rÊ   rË   r¡   ÚCHALLENGE_WAIT_SECONDSr   r>   r  r<   r=   Ú_WAITINGrÜ   r  rã   Ú_sleepr   rp   r  rk   r  rç   )	r÷   r  r   r;   r³   ÚverifyÚtold_interactiver  ro   s	   &        r(   Úwait_for_challenger*  •  sQ  € õ 0Ý6Ü×ÒÙØ—‘€IÜ�~Š~Ó¤#Ô&<¸i×>RÑ>RÓ"SÕS€Hñ ¨¯©Ô7€FØÐÙ	˜4 ×	(Ô	(¨FÜ˜× 3Ñ 3°S·^±^ÓDÌHÔTØ÷ 
)Ñ	(ô %,¨IÀ4Ô$HÐHˆ	”MÜ�	ÔÜ�nŠnÓ Ô)Ü˜YÓ'Ò3Ø÷ 
)Ñ	(ô �9×%Ñ%Ô&Ü! &×*=Ñ*=¸s¿~¹~ÓNˆFØœXÔ%Ø÷ 
)Ñ	(ð Ð,Ö,×5EÑ5EØ#'Ð Ü!Ó# yÖ0ÜÐQÔX[×XbÑXb×cð *÷ 
)ô  „JÙ÷# 
)×	(ús2   Â+F-Â:AF-Ä
AF-ÅF-ÅF-Å(F-Å;F-Æ-F=	c               ó    € V ^8„  d   QhRRRR/# )r#   Úcauser9   r$   r   r&   )r'   s   "r(   r)   r)   ¹  s   € ÷ ñ Ð/ð °Iñ r+   c                ó”   € \        V P                  4      '       d   R M\        \        ,          p\	        VR\        RR7      pWn        V# )z+The quick check couldn't finish. Try again.rB   TrC   )rã   r;   r   r   r   Ú	__cause__)r,  r   rÑ   s   &  r(   Ú_still_pendingr/  ¹  s>   € Ü@MÈeÏoÉo×@^Ò@^Ñ<Ü%Ô&=Õ>ð ä�g¨Ô5LÐX\Ô]€EØ„OØ€Lr+   c               ó    € V ^8„  d   QhRRRR/# )r#   ÚexchangezCallable[[], T]r$   r   r&   )r'   s   "r(   r)   r)   Á  s   € ÷ "ñ " ð "°Qñ "r+   c                ód  €  V ! 4       #   \          d   pTp Rp?MRp?ii ; i\        P                  4       '       g   \        4       R8X  d,   \	        \        TP                  RR7      4       \        T4      h\        4       P                  ;_uu_ 4        \        T4       RRR4       M  + '       g   i     M; i T ! 4       #   \          d7   p\        TP                  RR7      Tn        \        4        \        T4      hRp?i\         d#   pTP                  '       g   \        4        h Rp?ii ; i)a+  Run *exchange*; if the service asks for a browser challenge, work it (outside every lock:
the exception has already unwound them) and run *exchange* once more.

A background caller (:func:`background_caller`) never waits: the challenge is announced so a
desktop client can start clearing it, and the retryable error goes straight back.

A second ``challenge_required`` is not looped on: it surfaces as a retryable error whose copy
says what the user can do, the callers queued behind it fail fast for a while, and the next
attempt resumes the same ticket.Nrh   Fr!  )r9   r¼   rm   rp   r  rÜ   r;   r/  rÆ   r±   r*  rç   r   rF   r×   )r1  r÷   ÚfirstÚagainrÑ   s   &    r(   Úrun_with_challenger5  Á  sÜ   € ðÙ‹zÐøÜ ô Ø�ûðúô ‡�×ÒœNÓ,°	Ô9Ü”˜Ÿ™°UÔ;Ô<Ü˜UÓ#Ð#Ü	‹×	×	Ó	Ü˜5Ô!÷ 
×	×	Ð	úðÙ‹zÐøÜ ô $ô " %§/¡/¸uÔEˆŒÜŒ
Ü˜UÓ#Ð#ûÜô Ø��ˆÜÔØûðúsF   ‚	 ‰ ”› ÂB(Â(B8	Â<C ÃD/Ã1C?Ã?D/ÄD/ÄD*Ä*D/c               ó$   € V ^8„  d   QhRRRRRR/# )r#   r˜   r%   r<   r   r$   r?   r&   )r'   s   "r(   r)   r)   æ  s!   € ÷ 9ñ 9 nð 9Àsð 9Ètñ 9r+   c                ó²   € \        W4      pVf   \        4        R# VP                  '       g*   \        4       R8X  d   \	        \        VRR7      4       R# R# R# )zâA successful exchange may advertise a challenge nobody has to pass (the service is measuring
before it enforces). Only a desktop client runs it, hidden; a terminal never opens a browser
for something optional. Fire and forget.Nrg   Fr!  )rª   r×   r   rp   rø   rÜ   )r˜   r<   r;   s   && r(   Únote_optional_challengesr8  æ  sH   € ô (¨ÓA€IØÒÜÖØ××Ð¤NÓ$4¸	Ô$AÜ”'˜)°Ô7Ö8ñ %BÑr+   r“   )r²   r"  )ZÚ__conditional_annotations__rK   Ú
__future__r   Ú
contextlibÚcontextvarsÚloggingr”   rx   rk   r·   rÊ   Údataclassesr   r   r   Útypingr   r   r   r	   r
   Úurllib.parser   Úhermes_cli.anon_authr   r   r   r   r   Úhermes_cli.auth_constantsr   r   Ú	getLoggerrŸ   r|   ró   r%  r§   r¦   r¤   r¢   r¥   r`   ræ   r�   r   r   r9   rP   rO   rp   r}   r„   r�   r–   rª   r­   r¯   r¸   rÄ   r¹   r6   r¾   rº   Ú
ContextVarr¼   ÚcontextmanagerrÁ   rÆ   rÍ   rÓ   r×   rÜ   rß   rã   rç   rê   rî   rø   r
  r  r  r&  Úsleepr'  r*  r/  r5  r8  )r9  s   @r(   Ú<module>rG     sê  øðôõ> #ã Û Û Û Û Û 
Û Û ß 1Ñ 1ß 9Õ 9Ý !÷eõ eç 6à	×	Ò	Ð,Ó	-€à!Ð Ø'€ð
 Ð Ø'*¨CÐ $Ð Ð$àGKÈUÐTYÐ DÐ Ð*Ð,DØÐ ð !Ð àU€áˆCƒL€ñ �$Ô÷
fð 
fó ð
fô
%˜Iô 
%÷Aõ?õ>õLõXõXõõõ,	8ð ÷ð ó ðð �nŠnÓ€Ø*,€	Ð'Ó ,Ù›€ˆhÓ ð -8×,BÒ,BÐC^ÐhmÔ,n€Ð)Ó nð ×Ññ!ó ð!õKõõ	gõ4õõ$	õ3õLõ7õõõ"cõ*$õ&<ð* ,€Ø	�‰€õ!õHõ"÷J9r+   