+
    jHàj=±  ã                   óŒ  a € R„ ti0 t R 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
t
^ RIHtHtHt ^ RIHtHtHtHt ^ RIHtHtHt ^ RIHt ^ RI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& ]PN                  ! R
4      t(]! 4       t)]! RR4      t*]! R4      t+]! RR4      t,]! RR4      t-]! RR4      t.]! RR4      t/]! RR4      t0Rt1RR/t2R…t3]4! 4       t5] ^ k R…t6R R lt7R R lt8R†R R llt9R R lt:R‡R R  llt;R! R" lt<R# R$ lt=RˆR% R& llt>R‰R' R( llt?R) R* lt@R+ R, ltAR- R. ltBR/ R0 ltCR1 R2 ltDR3 R4 ltER5 R6 ltF]4! 4       tG] ^k ]G3R7 R8 lltHR9 R: ltIR;R<R= 3R>R?R@ 3RARBRC 3RDRERF 3RGRHRI 3/tJ] ^k RJ RK ltKRL RM ltLRN RO ltMRP RQ ltNRR RS ltOR;]LR>]MRD]NRG]O/tPR†RT RU lltQRV RW ltRR†RX RY lltSRZ R[ ltTR\ R] ltU])P­                  R^4      R†R_ R` ll4       tWRa Rb ltXRc Rd ltYRe Rf ltZ])P·                  Rg4      R†Rh Ri ll4       t\Rj Rk lt]Rl Rm lt^])P¿                  Rn4      R†Ro Rp ll4       t`Rq Rr ltaRs Rt ltb])P¿                  Ru4      R†Rv Rw ll4       tcRxtdRy Rz lte])P­                  R{4      RŠR| R} ll4       tf])P­                  R~4      R‹R R€ ll4       tg])P·                  R�4      R†R‚ Rƒ ll4       thR# )ŒzóOAuth provider dashboard routes: catalog/status, disconnect, and in-browser device-code login flows.

Extracted from ``hermes_cli.web_server``; helpers/state that tests monkeypatch on
``web_server`` stay there and are late-bound (cycle-safe).
N)ÚdatetimeÚtimezoneÚUTC)ÚAnyÚCallableÚDictÚOptional)Ú	APIRouterÚHTTPExceptionÚRequest)Ú
_codex_err)Ú	LateStateÚlate)Ú_external_process_cli_commandÚ_oauth_profile_nameÚ_oauth_sessionsÚ_oauth_sessions_lockÚ_truncate_token)ÚOAuthSubmitBody)Úconfig_scoped_to_threadÚscoped_to_threadzhermes_cli.web_serverÚ_profile_scopezhermes_cli.web_server_profilesÚ_require_tokenÚ_resolve_profile_dirÚ_OAUTH_PROVIDER_CATALOGzhermes_cli.web_server_oauthÚ_nous_sign_in_pollerÚ_minimax_pollerÚ_xai_device_pollerzhttps://auth.openai.comúContent-Typeúapplication/jsonc                ó0   € V ^8„  d   QhR\         R\        /# ©é   ÚrespÚreturn©r   Ústr)Úformats   "ÚA/home/ubuntu/.hermes/hermes-agent/hermes_cli/web_routers/oauth.pyÚ__annotate__r)   4   s   € ÷ >ñ >¤cð >¬cñ >ó    c                ód  aa€  V P                  4       o\        S\        4      '       d»   SP	                  R4      o\        S\        4      '       d>   V3R lR	 4        Uu. uF  q'       g   K  VNK  	  ppV'       d   RP                  V4      # S.V3R lR
 4       O FC  p\        V\        4      '       g   K  VP                  4       '       g   K3  VP                  4       u # 	  \        \        V RR4      ;'       g    R4      P                  4       R,          #   \         d    Ro ELi ; iu upi )z8Best-effort extraction of a short provider error detail.NÚerrorc              3   óv   <"  € T F.  p\        SP                  VR 4      4      P                  4       x € K0  	  R# 5i)Ú N)r&   ÚgetÚstrip)Ú.0Úkr,   s   & €r(   Ú	<genexpr>Ú._http_response_error_detail.<locals>.<genexpr>=   s/   øé € Ð yÑHxÀ1¤ U§Y¡Y¨q°"Ó%5Ó!6×!<Ñ!<×!>Ð!>ÓHxùs   ƒ69ú: c              3   óF   <"  € T F  pSP                  V4      x € K  	  R # 5i©N©r/   )r1   r2   Úpayloads   & €r(   r3   r4   @   s   øé € ÐbÑ7a°!˜wŸ{™{¨1Ÿ~˜~Ó7aùs   ƒ!Útextr.   :Niô  N)ÚmessageÚerror_descriptionÚcodeÚtype)Údetailr;   r<   )	ÚjsonÚ	ExceptionÚ
isinstanceÚdictr/   Újoinr&   r0   Úgetattr)r#   ÚsÚpartsÚvaluer,   r9   s   &   @@r(   Ú_http_response_error_detailrI   4   sô   ù€ ðØ—)‘)“+ˆô �'œ4× Ò Ø—‘˜GÓ$ˆÜ�eœT×"Ò"Ü yÑHxÔ yÓÑ y˜1Ó}~—Q�QÑ yˆEÐßØ—y‘y Ó'Ð'ØÐcÔbÑ7aÓbÓcˆEÜ˜%¤×%Ô%¨%¯+©+¯-¬-Ø—{‘{“}Ò$ñ dô Œw�t˜V RÓ(×.Ð.¨BÓ/×5Ñ5Ó7¸Õ=Ð=øô ô Ø‹ðüò
 @s   „D Á	D-Á-D-ÄD*Ä)D*c                ó0   € V ^8„  d   QhR\         R\        /# r!   r%   )r'   s   "r(   r)   r)   F   s   € ÷ ^ñ ^¬ð ^´ñ ^r*   c                ó¼   € \        V RR4      p\        V 4      pVP                  4       pRV9   d   RV9   g   RV9   d   RpMRpV'       d   V RV R	V R
2# V RV R
2# )z8Dashboard-facing OpenAI Codex device-code start failure.Ústatus_codeÚunknownÚdeviceÚauthoriÚenablezïOpenAI rejected the device-code login request. Your OpenAI account may need device-code authorization enabled before Hermes can start this dashboard login. Enable device-code authorization in OpenAI, then return here and click Login again.z…OpenAI rejected the device-code login request. Please try Login again from the dashboard after checking your OpenAI account settings.z (HTTP r5   Ú))rE   rI   Úlower)r#   Ústatusr?   rR   r;   s   &    r(   Ú_codex_device_code_start_errorrT   F   sƒ   € ä�T˜=¨)Ó4€FÜ(¨Ó.€FØ�L‰L‹N€EØ�5Ô˜i¨5Ô0°HÀÔ4EðAñ 	ðTð 	÷ 6<ˆgˆY�g˜f˜X R¨ x¨qÐ1Ð]ÀGÀ9ÈGÐTZÐS[Ð[\ÐA]Ð]r*   c                ó¢   € V ^8„  d   QhR\         R\         R\        \         ,          R\        \         \        \         \        3,          3,          /# )r"   Úprovider_idÚflowÚprofiler$   )r&   r   ÚtuplerC   r   )r'   s   "r(   r)   r)   Z   sE   € ÷ ñ ¤Cð ¬sð ¼XÄc½]ð ÔV[Ô\_ÔaeÔfiÔknÐfnÕaoÐ\oÕVpñ r*   c                óö   € \         P                  ! ^4      pRVRV RVR\        V4      R\        P                  ! 4       RRRR	/p\        ;_uu_ 4        V\
        V&   R	R	R	4       W43#   + '       g   i     Y43# ; i)
zICreate + register a new OAuth session, return (session_id, session_dict).Ú
session_idÚproviderrW   rX   Ú
created_atrS   ÚpendingÚerror_messageN)ÚsecretsÚtoken_urlsafer   Útimer   r   )rV   rW   rX   ÚsidÚsesss   &&&  r(   Ú_new_oauth_sessionre   Z   sv   € ä
×
Ò
 Ó
#€Cà�c˜: {°F¸DÀ)ÔM`ÐahÓMiØ”d—i’i“kØ�)Ø˜ð	€D÷ 
Ö	Ø#Œ˜Ñ÷ 
àˆ9Ð÷ 
Ö	àˆ9Ðús   Á
A&Á&A8	c                ó(   € V ^8„  d   QhR\         RR/# )r"   rc   r$   N©r&   )r'   s   "r(   r)   r)   h   s   € ÷ 'ñ 'œSð ' Tñ 'r*   c                óŠ   € \         ;_uu_ 4        \        P                  ! V R4       RRR4       R#   + '       g   i     R# ; i)zYForget a session that never got started, so the dashboard does not poll a corpse forever.N)r   r   Úpop)rc   s   &r(   Ú_drop_oauth_sessionrj   h   s'   € ç	Ö	Ü×Ò˜C Ô&÷ 
×	×	Ò	ús	   �1±A	c                ó4   € V ^8„  d   QhR\         R\         RR/# )r"   rc   Úprefixr$   Nrg   )r'   s   "r(   r)   r)   n   s&   € ÷ gñ gœsð g¬Cð gÀ4ñ gr*   c           	      óJ  a aa€ \         ;_uu_ 4        \        P                  ! S4      oR R R 4       R VVV 3R llp\        P                  ! 4       p\
        P                  ! VP                  V3RV RSR,           2R7      P                  4        R #   + '       g   i     Lq; i)Nc                ó   € V ^8„  d   QhRR/# ©r"   r$   N© )r'   s   "r(   r)   Ú#_start_poller.<locals>.__annotate__r   s   € ÷ %ñ %�ñ %r*   c                  ó\   <€  S! S4       ^ RI Hp  V ! S4       R#   ^ RI Hp  T ! S4       i ; i)é    ©Úsettle_oauth_setupN)Ú-hermes_cli.observability.shared_metrics_setupru   )ru   rd   rc   Útargets    €€€r(   ÚrunÚ_start_poller.<locals>.runr   s*   ø€ ð	%Ù�3ŒKåXÙ˜tÖ$øõ YÙ˜tÕ$ús   ƒ ›+TÚ-:Né   N)rw   ÚargsÚdaemonÚname)	r   r   r/   ÚcontextvarsÚcopy_contextÚ	threadingÚThreadrx   Ústart)rw   rc   rl   rx   Úcontextrd   s   ff&  @r(   Ú_start_pollerr…   n   sx   ú€ ß	Ö	Ü×"Ò" 3Ó'ˆ÷ 
÷%ò %ô ×&Ò&Ó(€GÜ×Ò˜GŸK™K¨s¨f¸TÈ6È(ÐRSÐTWÐXZÕT[ÐS\ÐH]Ô^×dÑdÖf÷ 
×	ús   ’BÂB"	c                ó(   € V ^8„  d   QhR\         RR/# ©r"   r[   r$   Nrg   )r'   s   "r(   r)   r)   €   s   € ÷ ñ ¬ð °ñ r*   c                óØ   € ^ RI HpHpHp \        ;_uu_ 4        \
        P                  ! V4      pRRR4       Xf   V! V R4       R# V! WP4       V! V4       R#   + '       g   i     L1; i)zNHand the setup flow to its session; settle it now if the poller already ended.)Úattach_oauth_setupÚfinish_provider_setupru   NÚ	abandoned)rv   r‰   rŠ   ru   r   r   r/   )rW   r[   r‰   rŠ   ru   rd   s   &&    r(   Ú_track_oauth_setuprŒ   €   sT   € ÷ñ ÷ 
Ö	Ü×"Ò" :Ó.ˆ÷ 
à‚|Ù˜d KÔ0ÙÙ�tÔ"Ù�tÖ÷ 
×	ús   ™AÁA)	c                óº   € V ^8„  d   QhR\         R\        \         ,          R\        \         \        3,          R\        R\        R\        \         \        3,          /# )r"   rV   rX   ÚfieldsÚ
expires_inÚpoll_intervalr$   )r&   r   rC   r   Úint)r'   s   "r(   r)   r)   Ž   sR   € ÷ ñ ÜðÜ'¬�}ðÜ>BÄ3ÌÀ8½nðä-0ðäADðô 
Œ#Œsˆ(…^ñr*   c                óv   € \        V RVR7      w  r‰V	P                  V4       \        W(4       RVRRRVRVRVRV/# )	z]Register a device-code session carrying ``fields``, start its poller, return the /start body.Údevice_code©rX   r[   rW   Ú	user_codeÚverification_urlr�   r�   )re   Úupdater…   )
rV   rX   ÚpollerrŽ   r•   r–   r�   r�   rc   rd   s
   &&&&&&&&  r(   Ú_device_session_startedr™   Ž   sN   € ô
 # ;°ÀwÔO�I€CØ‡K�K�ÔÜ�&Ôà�c˜6 =°+¸yØÐ,¨l¸JÈÐYfðð r*   c                ó`   € V ^8„  d   QhR\         \        .\        3,          R\        R\        /# )r"   ÚfnÚtimeoutr$   )r   r   Úfloat)r'   s   "r(   r)   r)   œ   s-   € ÷ 
*ñ 
*œ(¤C 5¬# :Õ.ð 
*¼ð 
*Ô[^ñ 
*r*   c              ‹  ól   a aaa"  € ^ RI oVV VV3R lp\        P                  ! V4      G Rj  x€L
 #  L5i)zORun ``fn(client)`` off-loop with a short-lived JSON-accepting ``httpx.Client``.Nc                  ó°   <€ SP                   ! RR SP                  S4      RRR//SB ;_uu_ 4       p S! V 4      uuRRR4       #   + '       g   i     R# ; i)rœ   ÚheadersÚAcceptr   Nrp   )ÚClientÚTimeout)ÚclientÚclient_kwargsr›   Úhttpxrœ   s    €€€€r(   Ú_callÚ_httpx_call.<locals>._call    sZ   ø€ Ø�\Š\ñ 
Ø—M‘M 'Ó*ð
Ø5=Ð?QÐ4Rð
ØVc÷
ò 
àÙ�f“:÷
÷ 
÷ 
ó 
ús   ±AÁA	)r¦   ÚasyncioÚ	to_thread)r›   rœ   r¥   r§   r¦   s   ffl @r(   Ú_httpx_callr«   œ   s,   ûé € ã÷ð ô ×"Ò" 5Ó)×)Ð)Ñ)ùs   †'4­2®4c                ój   € V ^8„  d   QhR\         \        \        3,          R\        R\        R\        /# )r"   rd   r[   Ústager$   )rC   r&   r   Úbool)r'   s   "r(   r)   r)   °   s1   € ÷ ñ œ4¤¤S �>ð ´sð Ä3ð ÔPTñ r*   c                 ód   € V P                  R 4      '       g   R# \        P                  RW!4       R# )Ú	cancelledFz9oauth/device: openai-codex login cancelled%s (session=%s)T)r/   Ú_logÚinfo)rd   r[   r­   s   &&&r(   Ú_codex_cancelledr³   °   s&   € Ø�8‰8�K× Ò ÙÜ‡I�IÐIÈ5Ô]Ùr*   c                ó$   € V ^8„  d   QhR\         /# ©r"   r$   )r   )r'   s   "r(   r)   r)   ·   s   € ÷ kñ kœCñ kr*   c                óX   € ^ RI Hp V P                  V P                  R4      RV./R7      # )a  15s ``httpx.Client`` for the device-login flow with the CLI flow's 1 MiB auth-body cap (#55253).

The helpers take the ``httpx`` module as a parameter (tests inject a scripted one), so the
dashboard builds its own client here and only shares the response hook, not the client factory.
)Ú_cap_codex_response_bodyç      .@Úresponse)rœ   Úevent_hooks)Úhermes_cli.auth_codexr·   r¢   r£   )r¦   r·   s   & r(   Ú_codex_clientr¼   ·   s,   € õ ?à�<‰< §¡¨dÓ 3À*ÐOgÐNhÐAiˆ<ÓjÐjr*   c                ó<   € V ^8„  d   QhR\         R\        R\        /# )r"   ÚurlÚkwargsr$   )r&   r   )r'   s   "r(   r)   r)   Â   s!   € ÷ ñ œCð ¬3ð ´3ñ r*   c                ó<  € ^ RI Hp ^^rT  \        V 4      ;_uu_ 4       pVP                  ! V3/ VB uuRRR4       #   + '       g   i     KD  ; i  \         d@   pYE8X  g   T! T4      '       g   h \
        P                  ! T4       T^,          p Rp?KŒ  Rp?ii ; i)aR  One 15s POST for the device-login flow, mirroring ``auth_codex._codex_login_post``.

A transient transport blip (a dropped connection mid-flow) is retried twice with a small
linear backoff before propagating: losing the token exchange to a single SSL EOF wastes a
device-code approval the user already completed in the browser (#114610).
©Ú_is_transient_transport_errorN)r»   rÂ   r¼   ÚpostrA   rb   Úsleep)r¦   r¾   r¿   rÂ   ÚattemptÚattemptsr¤   Úexcs   &&,     r(   Ú_codex_postrÈ   Â   s|   € õ Dà˜1ˆXØ
ð	Ü˜u×%Ô%¨Ø—{’{ 3Ñ1¨&Ñ1÷ &×%×%Ó%ûäô 	ØÔ"Ñ*GÈ×*LÒ*LØÜ�JŠJ�wÔØ�q�LŽGûð		ús7   ŒA Ÿ=²
A ½A	ÁA ÁA ÁBÁBÁ0 BÂBc                óT   € V ^8„  d   QhR\         R\        \        .\        3,          /# )r"   rS   r$   )r‘   r   r&   rA   )r'   s   "r(   r)   r)   ×   s*   € ÷ Vñ Vœcð V¤h´¨u´iÐ/?Õ&@ñ Vr*   c                óP   € V R9   d   \         # V R9   g   V R8¼  d   \        # \        # )z¥Exception type for a non-200 Codex reply: 401/403 is OpenAI refusing this account/client;
408/429/5xx is the service down or shedding load (a network-class failure).éô  >   é‘  é“  >   é˜  é­  )r   ÚConnectionErrorÚRuntimeError©rS   s   &r(   Ú_codex_http_errorrÓ   ×   s*   € ð �ÔÜÐØ$¨
Ô2°fÀ´mŒ?ÐUÌÐUr*   c                óF   € V ^8„  d   QhR\         \        \        3,          /# rµ   ©rC   r&   r   )r'   s   "r(   r)   r)   ß   s   € ÷ ñ ¤t¬C´¨H¥~ñ r*   c           	     ó–  € ^ RI Hp \        V \         R2RV/\        R7      pVP
                  ^È8w  d%   \        VP
                  4      ! \        V4      4      hVP                  4       p\        ^\        VP                  RR4      4      4      VR&   VP                  R4      '       d   VP                  R4      '       g   \        R	4      hV# )
zSStep 1: request device code; returns device_data with ``interval`` clamped (>= 3s).)ÚCODEX_OAUTH_CLIENT_IDz!/api/accounts/deviceauth/usercodeÚ	client_id©r@   r    ÚintervalÚ5r•   Údevice_auth_idz8device-code response missing user_code or device_auth_id)Úhermes_cli.authr×   rÈ   Ú_CODEX_ISSUERÚ_JSON_HEADERSrL   rÓ   rT   r@   Úmaxr‘   r/   rÑ   )r¦   r×   r#   Údevice_datas   &   r(   Ú_codex_request_user_coderâ   ß   s°   € å5äØ”-�Ð AÐBÈ+ÐWlÐImÜô€Dð ×Ñ˜3ÔÜ × 0Ñ 0Ô1Ô2PÐQUÓ2VÓWÐWØ—)‘)“+€KÜ! !¤S¨¯©¸ÀSÓ)IÓ%JÓK€K�
ÑØ�?‰?˜;×'Ò'¨{¯©Ð?O×/PÒ/PÜÐUÓVÐVØÐr*   c                ó^   € V ^8„  d   QhR\         \        \        3,          R\        R\        /# )r"   rd   r[   r$   rÕ   )r'   s   "r(   r)   r)   ð   s)   € ÷ "ñ "¬4´´S°­>ð "Äsð "Ìsñ "r*   c           	     óŒ  € ^ RI Hp \        P                  ! 4       VR,          ,           pRVR,          RVR,          /p^p^ p\	        V 4      ;_uu_ 4       p\        P                  ! 4       V8  dØ   \        W4      '       d   \        uuRRR4       # \        P                  ! VR,          4       \        W4      '       d   \        uuRRR4       #  VP                  \         R2V\        R7      p	^ pT	P                  ^È8X  d   T	P!                  4       uuRRR4       # T	P                  R9   d   KÙ  \        RT	P                   24      h RRR4       R#   \         dS   p
T! T
4      '       g   h T^,          pYv8¼  d   \        R	T R
T
 24      T
h\        P                  RT4        Rp
?
EKT  Rp
?
ii ; i  + '       g   i     R# ; i)zSStep 2: poll until authorized. ``None`` = expired; ``_CANCELLED`` = user cancelled.rÁ   r�   rÜ   r•   NrÚ   z/api/accounts/deviceauth/tokenrÙ   z#deviceauth/token poll failed after z consecutive transport errors: zEoauth/device: openai-codex poll transport blip, retrying (session=%s)zdeviceauth/token poll returned >   rÍ   é”  )r»   rÂ   rb   Ú	monotonicr¼   r³   Ú
_CANCELLEDrÄ   rÃ   rÞ   rß   rA   rÑ   r±   r²   rL   r@   )r¦   rd   r[   rÂ   Údeadliner9   Úmax_consecutive_blipsÚconsecutive_blipsr¤   ÚpollrÇ   s   &&&        r(   Ú_codex_poll_authorizationrì   ð   s¤  € åCä�~Š~Ó $ |Õ"4Õ4€HØ Ð&6Õ!7¸ÀdÈ;ÕFWÐX€GØÐØÐÜ	�u×	Ô	 Ü�nŠnÓ Ô)Ü ×1Ò1Ü!÷ 
Ò	ô �JŠJ�t˜JÕ'Ô(Ü ×1Ò1Ü!÷ 
Ò	ðØ—{‘{Ü$�oÐ%CÐDÈ7Ô\ið #ó k�ð !"ÐØ×Ñ 3Ô&Ø—y‘y“{÷- 
Ò	ð. ×Ñ :Ô-ÙÜÐ!@À×AQÑAQÐ@RÐSÓTÐTð1 *÷ 
ñ4 øô! ô 	Ù4°S×9Ò9ØØ! QÕ&Ð!Ø$Ô=Ü&Ø=Ð>OÐ=Pð Q.Ø.1¨Uð4ó5à:=ð>ô —	‘	ÐaÐcmÔnÞûð	ú÷ 
Ö	ñ4 úsC   Á1F2Â3F2ÃEÃ/"F2Ä+F2ÅF/ÅAF*Æ#F2Æ*F/Æ/F2Æ2G	c                ót   € V ^8„  d   QhR\         \        \        3,          R\         \        \        3,          /# )r"   Ú	code_respr$   rÕ   )r'   s   "r(   r)   r)     s.   € ÷ nñ n¬T´#´s°(­^ð nÄÄSÌ#ÀXÅñ nr*   c                óô  € ^ RI HpHp VP                  RR4      pVP                  RR4      pV'       d	   V'       g   \	        R4      h\        WRRRVR\         R	2R
VRV/RR/R7      pVP                  ^È8w  d)   \        VP                  4      ! RVP                   24      hVP                  4       pVP                  R4      '       g   \	        R4      hRVP                  RR4      RVP                  RR4      /# )z/Step 3: exchange authorization_code for tokens.)r×   ÚCODEX_OAUTH_TOKEN_URLÚauthorization_coder.   Úcode_verifierz=device-auth response missing authorization_code/code_verifierÚ
grant_typer=   Úredirect_uriz/deviceauth/callbackrØ   r   z!application/x-www-form-urlencoded)Údatar    ztoken exchange returned Úaccess_tokenz*token exchange did not return access_tokenÚrefresh_token)
rÝ   r×   rð   r/   rÑ   rÈ   rÞ   rL   rÓ   r@   )r¦   rî   r×   rð   rñ   rò   Ú
token_respÚtokenss   &&      r(   Ú_codex_exchange_tokensrú     sû   € çLà"Ÿ™Ð';¸RÓ@ÐØ—M‘M /°2Ó6€Mß§]ÜÐZÓ[Ð[ÜØàÐ.°Ð8JØœ}˜oÐ-AÐBØÐ.°Àð
ð
  Ð!DÐEô€Jð ×Ñ Ô$Ü 
× 6Ñ 6Ô7Ð:RÐS]×SiÑSiÐRjÐ8kÓlÐlØ�_‰_Ó€FØ�:‰:�n×%Ò%ÜÐGÓHÐHØ˜FŸJ™J ~°rÓ:¸OÈVÏZÉZÐXgÐikÓMlÐmÐmr*   c                ó(   € V ^8„  d   QhR\         RR/# r‡   rg   )r'   s   "r(   r)   r)   .  s   € ÷ 4,ñ 4,¬ð 4,°ñ 4,r*   c                ó  €  ^ RI p\        V4      p\        ;_uu_ 4        \        P                  ! V 4      pV'       g    RRR4       R# VP                  VR,          \         R2VR,          VR,          \        \        P                  ! 4       \        ,           R7       VP	                  R4      pRRR4       \        VXV 4      pVf$   \        ;_uu_ 4        RVR	&   R
VR&   RRR4       R# V\        J g   \        W0R4      '       d   R# \        W4      p^ RIHp \        X4      ;_uu_ 4        \        ;_uu_ 4        \        W0R4      '       d    RRR4       RRR4       R# V! V4       RVR	&   RRR4       RRR4       \         P#                  RV 4       R#   + '       g   i     Lð; i  + '       g   i     R# ; i  + '       g   i     LW; i  + '       g   i     Lb; i  \$         d�   p^ RIHp	 \         P+                  RY4       \        ;_uu_ 4        \        P                  ! T 4      p
T	! Y¨4       T
'       d   RT
R	&   \-        T4      T
R&   RRR4        Rp?R#   + '       g   i      Rp?R# ; iRp?ii ; i)zCRun the complete OpenAI Codex device-code flow (see comment above).Nr•   z/codex/devicerÜ   rÚ   )r•   r–   rÜ   rÚ   r�   Ú
expires_atrX   ÚexpiredrS   z#Device code expired before approvalr_   z before token exchange)Ú_save_codex_tokensz before token saveÚapprovedz7oauth/device: openai-codex login completed (session=%s))Únote_oauth_failurez0codex device-code worker failed (session=%s): %sr,   )r¦   râ   r   r   r/   r—   rÞ   Ú_CODEX_EXPIRES_INrb   rì   rç   r³   rú   rÝ   rÿ   r   r±   r²   rA   rv   r  Úwarningr&   )r[   r¦   rá   rd   Úsession_profilerî   rù   rÿ   Úer  rF   s   &          r(   Ú_codex_full_login_workerr  .  så  € ð2,Ûä.¨uÓ5ˆß!Ö!Ü"×&Ò& zÓ2ˆDßØ÷ "Ñ!ð �K‰KØ% kÕ2ÌÀÐVcÐEdØ*Ð+;Õ<À{ÐS]ÕG^Ü,¼¿º»ÔGXÕ9Xð ô ð #Ÿh™h yÓ1ˆO÷ "ô .¨e°T¸:ÓFˆ	ØÒß%Ö%Ø!*��X‘Ø(M��_Ñ%÷ &ñ Øœ
Ó"Ô&6°tÐIa×&bÒ&bÙä'¨Ó9ˆÝ6ô ˜O×,Õ,×.BÖ.BÜ Ð2F×GÒGØ÷ /C×,Ñ,ñ ˜vÔ&Ø'ˆD�‰N÷	 /C×,ô
 	�	‰	ÐKÈZÖX÷K "×!ú÷  &Ö%ñ ú÷ /C×.Bú×,×,ûô ô ,ÝTÜ�‰ÐGÈÔWß!Ö!Ü×#Ò# JÓ/ˆAÙ˜qÔ$ßØ%��(‘Ü%(¨£V��/Ñ"÷ "×!×!×!Ò!þð,úsÄ   ‚G$ Ÿ F¿G$ Á	A&FÂ/'G$ ÃF*Ã!G$ Ã+G$ Ä	$G$ Ä-GÄ<F>	ÅGÅG$ Å"F>	Å/GÅ7G$ ÆF'	Æ"G$ Æ*F;	Æ5G$ Æ;G$ Æ>GÇ	GÇG!	ÇG$ Ç$I>Ç/*I9È:I!ÉI9É!I6É,I9É6I9É9I>c                óR   € V ^8„  d   QhR\         R\         \        \        3,          /# )r"   Úrawr$   rÕ   )r'   s   "r(   r)   r)   h  s$   € ÷ 	ñ 	Ü	ð	ä	Œ#Œsˆ(…^ñ	r*   c                 ón   € R \        V P                  R 4      4      RVRVRVRVRV/pV\        Jd   WgR&   V# )Ú	logged_inÚsourceÚsource_labelÚtoken_previewrý   Úhas_refresh_tokenÚlast_refresh)r®   r/   Ú_OMIT)r  r  r  r  rý   r  r  Úcards   &&&&&&& r(   Ú_status_cardr  h  sM   € ð 	”T˜#Ÿ'™' +Ó.Ó/°¸6À>ÐS_Ø˜¨°jÐBUÐWhð€Dð œ5Ó Ø+ˆ^ÑØ€Kr*   c                óF   € V ^8„  d   QhR\         R\        \        ,          /# )r"   rH   r$   )r   r   r&   )r'   s   "r(   r)   r)   t  s"   € ÷ Wñ WœCð W¤H¬S¥Mñ Wr*   c                óx   € V '       d2   \         P                  ! V R,          \        R7      P                  4       # R# )zQEpoch ms (Qwen CLI ``expiry_date``) -> the aware ISO string the other cards send.éè  )ÚtzN)r   Úfromtimestampr   Ú	isoformat)rH   s   &r(   Ú_epoch_ms_to_isor  t  s*   € çGLŒ8×!Ò! %¨$¥,´3Ô7×AÑAÓCÐVÐRVÐVr*   ÚnousÚget_nous_auth_status_localc                 ó0  € / \        T R V P                  R4      ;'       g    R\        V P                  R4      4      V P                  R4      \        V P                  R4      4      4      CR\        V P                  R4      4      RV P                  R4      /C# )Únous_portalÚportal_base_urlzNous Portalrö   Úaccess_expires_atr  Ú	free_tierÚaccount_tier)r  r/   r   r®   ©Úrs   &r(   Ú<lambda>r$    s‡   € ð 6U¼Ø	ˆ=˜!Ÿ%™%Ð 1Ó2×CÐC°mÜ˜Ÿ™˜nÓ-Ó.°·±Ð6IÓ0JÌDÐQR×QVÑQVÐWjÓQkÓLló9ð 6Uð ”D˜Ÿ™˜{Ó+Ó,¨n¸a¿e¹eÀNÓ>Sò6Ur*   úopenai-codexÚget_codex_auth_statusc                 óÔ   € \        Y P                  R 4      ;'       g    RV P                  R4      ;'       g    R\        V P                  R4      4      RRV P                  R4      4      # )r  Úopenai_codexÚ	auth_modezOpenAI CodexÚapi_keyNFr  ©r  r/   r   r"  s   &r(   r$  r$  ƒ  sO   € ¼Ø	�5‰5�‹?×,Ð,˜n¨a¯e©e°KÓ.@×.RÐ.RÀNÜ˜Ÿ™˜iÓ(Ó)¨4°¸¿¹¸nÓ8Mô9r*   z
qwen-oauthÚget_qwen_auth_statusc                 óä   € \        T R V P                  R4      ;'       g    R\        V P                  R4      4      \        V P                  R4      4      \	        V P                  R4      4      4      # )Úqwen_cliÚ	auth_filezQwen CLIr*  Úexpires_at_msr  )r  r/   r   r  r®   r"  s   &r(   r$  r$  ‡  sX   € ´\Ø	ˆ:�q—u‘u˜[Ó)×7Ð7¨ZÜ˜Ÿ™˜iÓ(Ó)Ô+;¸A¿E¹EÀ/Ó<RÓ+SÔUYÐZ[×Z_ÑZ_Ð`sÓZtÓUuô6r*   úminimax-oauthÚget_minimax_oauth_auth_statusc           	      óh   € \        V R RV P                  RR4       R2RV P                  R4      R4      # )Úminimax_oauthz	MiniMax (ÚregionÚglobalrQ   Nrý   T)r  r/   r"  s   &r(   r$  r$  ‹  s7   € ÄØ	ˆ?˜i¨¯©¨h¸Ó(AÐ'BÀ!ÐDÀdÈAÏEÉEÐR^ÓL_ÐaeôBr*   ú	xai-oauthÚget_xai_oauth_auth_statusc                 ó  € \        Y P                  R 4      ;'       g    RV P                  R4      ;'       g    V P                  R 4      ;'       g    R\        V P                  R4      4      RRV P                  R4      4      # )r  Ú	xai_oauthÚ
auth_storezxAI Grok OAuthr*  NTr  r+  r"  s   &r(   r$  r$  Ž  s`   € ¼Ø	�5‰5�‹?×)Ð)˜k¨1¯5©5°Ó+>×+eÐ+eÀ!Ç%Á%ÈÃ/×+eÐ+eÐUeÜ˜Ÿ™˜iÓ(Ó)¨4°°q·u±u¸^Ó7Lô:r*   c                óR   € V ^8„  d   QhR\         R\        \         \        3,          /# )r"   rV   r$   )r&   rC   r   )r'   s   "r(   r)   r)   •  s"   € ÷  ñ  ¬#ð  ¼TÄ#ÄsÀ(½^ñ  r*   c                ó¢  €  Ve   V! 4       # ^ RI Hp \        P                  V 4      pVe   Vw  rEV! \	        W$4      ! 4       4      # VP                  V 4      p\        V\        4      '       Ed9   RV9   Ed1   \        TVP                  R4      ;'       g    VP                  R4      ;'       g    T VP                  R4      ;'       gg    VP                  R4      ;'       gN    VP                  R4      ;'       g5    VP                  R	4      ;'       g    VP                  R
4      ;'       g    R\        VP                  R4      ;'       g    VP                  R4      4      VP                  R4      ;'       g    VP                  R4      \        VP                  R4      4      4      # RR/#   \         d   pRRR\        T4      /u Rp?# Rp?ii ; i)z@Dispatch to the right status helper for an OAuth provider entry.N)Úauthr
  r  r\   r  r;  Úauth_store_pathÚbase_urlr~   r.   rö   r*  rý   r  r  Fr,   )Ú
hermes_clir>  Ú_PROVIDER_STATUSr/   rE   Úget_auth_statusrB   rC   r  r   r®   rA   r&   )rV   Ú	status_fnÚhauthÚentryÚgetterÚshaper  r  s   &&      r(   Ú_resolve_provider_statusrI  •  s   € ð5ØÒ Ù“;ÐÝ,Ü ×$Ñ$ [Ó1ˆØÒØ!‰MˆFÙœ Ô/Ó1Ó2Ð2ð ×#Ñ# KÓ0ˆÜ�cœ4× Ó  [°CÕ%7ÜØØ—‘˜Ó!×GÐG S§W¡W¨ZÓ%8×GÐG¸KØ—‘˜Ó'÷ @ð @¨3¯7©7°<Ó+@÷ @ð @ÀCÇGÁGÐL]ÓD^÷ @ð @Ø—7‘7˜:Ó&÷@ð @Ø*-¯'©'°&«/÷@ð @Ø=?Ü §¡¨Ó 7× MÐ M¸3¿7¹7À9Ó;MÓNØ—‘˜Ó%×EÐE¨¯©Ð1DÓ)EÜ�S—W‘WÐ0Ó1Ó2óð ð ˜ÐÐøô ô 5Ø˜U G¬S°«VÐ4Õ4ûð5ús_   ‚
F* �8F* ÁAF* ÂF* Â-F* ÃF* Ã F* Ã9F* ÄF* Ä+F* Å
,F* Å7.F* Æ*GÆ5G	ÇGÇ	Gc                óh   € V ^8„  d   QhR\         \        ,          R\        \        \        3,          /# ©r"   rX   r$   ©r   r&   rC   r   )r'   s   "r(   r)   r)   ²  s*   € ÷ @ñ @¬8´C­=ð @¼TÄ#ÄsÀ(½^ñ @r*   c              ƒ  óF  a a	a
a"  € ^ RI Hp ^ RIHp ^ RIHo	 VR,          p\        P                  ! R4      ;'       g+    \        P                  ! R4      ;'       g    VP                  P                  R4      p\        RRS R	7      w  poR
 V3R llp\        P                  V3R l4       pVP                  RVRVV	V 3R lR7      o
 \        V
3R l4      G Rj  x€L
 p\'        TRR4      R8w  d^   \        P                   ! \        4      ;_uu_ 4        S
P#                  4        RRR4       \%        T4       \)        RTP*                  R7      h\,        ;_uu_ 4        SP/                  \1        YCP2                  TP4                  RTP6                  \8        P8                  ! 4       TP:                  ,           S
R7      4       RRR4       \=        \>        T4       RTRRRTP@                  RTPB                  RTP:                  RTP6                  /#  EL3  \         d]    \        P                   ! \        4      ;_uu_ 4        S
P#                  4        RRR4       M  + '       g   i     M; i\%        T4       h i ; i  + '       g   i     EL_; i  + '       g   i     L×; i5i)aF  Start a Nous sign-in: the shared ``anon_auth.run_sign_in`` flow, the plain device-code login.
This route creates the generator, pulls its first state (the device page link and code) and
hands that to the UI, then the poller drains the rest. A free tier the account replaces hands
its apps over after the save, inside the flow.)Ú	anon_auth)ÚPROVIDER_REGISTRY)Ú_config_profile_scoper  ÚHERMES_PORTAL_BASE_URLÚNOUS_PORTAL_BASE_URLÚ/r“   r”   c                ó$   € V ^8„  d   QhR\         /# rµ   ©r®   )r'   s   "r(   r)   Ú-_start_nous_device_code.<locals>.__annotate__Ã  s   € ÷ /ñ /œñ /r*   c                  ó’   <€ \         ;_uu_ 4        \        S P                  R 4      4      uuRRR4       #   + '       g   i     R# ; i)r°   N)r   r®   r/   ©rd   s   €r(   Ú
_cancelledÚ+_start_nous_device_code.<locals>._cancelledÃ  s)   ø€ ß!Ö!Ü˜Ÿ™ Ó-Ó.÷ "×!×!Ó!ús	   �5µA	c               3   ó°   <"  € \         ;_uu_ 4        S P                  R 4      '       d   R S R&   Rx € MRx € RRR4       R#   + '       g   i     R# ; i5i)r°   rS   FTN©r   r/   rX  s   €r(   Ú_persist_guardÚ/_start_nous_device_code.<locals>._persist_guardÇ  s>   øé € ÷ "Ö!Ø�x‰x˜×$Ò$Ø!,��X‘Ø“à’
÷ "×!×!Ò!üs   ƒA’&A¸
AÁA	Á	Ar¸   Tc                  ó&   <€ S ! \        S4      4      # r7   )r   )rP  rX   s   €€r(   r$  Ú)_start_nous_device_code.<locals>.<lambda>Ù  s   ø€ Ñ+Ô,?ÀÓ,HÔIr*   )Útimeout_secondsr°   Úreplace_accountÚpersist_guardÚscopec                 ó   <€ \        S4      # r7   )Únext)Ú_clientÚgens   &€r(   r$  r`  Ü  s	   ø€ ´$°s´)r*   NÚkindr.   r=   é�  )r?   )r  rØ   rd  r“   rÚ   rý   Ú_sign_inr[   rW   r•   r–   r�   r�   )"rA  rN  rÝ   rO  Úhermes_cli.web_server_profilesrP  ÚosÚgetenvr  Úrstripre   Ú
contextlibÚcontextmanagerÚrun_sign_inr«   rA   ÚsuppressÚcloserj   rE   r
   Úcopy_terminalr   r—   rC   rØ   rd  rÚ   rb   r�   r…   r   r=   Úlink)rX   rN  rO  Úpconfigr  rc   rY  r]  ÚfirstrP  rh  rd   s   f        @@@r(   Ú_start_nous_device_codery  ²  s	  ûé € õ
 %Ý1ÝDØ Õ'€Gä
�	Š	Ð*Ó+×kÐk¬r¯yªyÐ9OÓ/P×kÐkÐT[×TkÑTkß�fˆSƒkð ô # 6¨=À'ÔJ�I€Cˆ÷/ð /ô ×Ñôó ðð ×
Ñ
ØØàØ$õ Jð  ó 	€CðÜ!Ô";Ó<×<ˆô ˆu�f˜bÓ! VÔ+Ü× Ò ¤×+Õ+Ø�I‰IŒK÷ ,ä˜CÔ Ü˜C¨×(;Ñ(;Ô<Ð<ß	Ö	à�‰”DØ+×7HÑ7HÐPW×P]ÑP]Ø U§^¡^Ü—y’y“{ U×%5Ñ%5Õ5ÀôEô 	F÷ 
ô Ô&¨Ô,à�c˜6 =°+¸u¿z¹zØ˜EŸJ™J¨°e×6FÑ6FØ˜Ÿ™ðð ò% =øÜô Ü× Ò ¤×+Õ+Ø�I‰IŒK÷ ,×+×+Ð+úä˜CÔ Øð	ú÷ ,×+Ð+ú÷ 
×	üs�   †AJ!ÁA*J!ÃH ÃHÃH Ã4J!ÄI:Ä$8J!ÅA#JÆ?AJ!ÈH È-I7È=IÉ	I7ÉI'É"I7É7J!É:J	Ê	J!ÊJ	ÊJ!c                óh   € V ^8„  d   QhR\         \        ,          R\        \        \        3,          /# rK  rL  )r'   s   "r(   r)   r)   õ  s&   € ÷ ñ ¬H´S­Mð ¼dÄ3ÌÀ8½nñ r*   c              ƒ   ó2  "  € \        R RV R7      w  r\        \        VRR7       \        P                  ! 4       ^
,           p\        P                  ! 4       V8  d|   \
        ;_uu_ 4        \        P                  ! V4      pRRR4       X'       d'   VP                  R4      '       g   VR,          R8w  d   M \        P                  ! R	4      G Rj  x€L
  K•  \
        ;_uu_ 4        \        P                  ! V/ 4      pRRR4       XP                  R4      R
8X  dO   ^ RI
Hp \        RVP                  R4      ;'       g    RR7      pVP                  V4      ;'       g    RVn        VhVP                  R4      '       g   \        RRR7      hRTRRRVR,          RVR,          R\        VP                  R4      ;'       g    R4      R\        VP                  R4      ;'       g    ^4      /#   + '       g   i     ELu; i EL1  + '       g   i     EL; i5i)r%  r“   r”   zoauth-codex)rl   Nr•   rS   r^   gš™™™™™¹?r,   )Ú_OAUTH_FAILURE_KEYrË   r_   zdevice-auth failed©rL   r?   Úotheréø  z2device-auth timed out before returning a user coder[   rW   r–   r�   é„  r�   rÚ   )re   r…   r  rb   ræ   r   r   r/   r©   rÄ   rv   r|  r
   Úsetup_failure_classr‘   )rX   rc   Ú_rè   rF   r|  Úerrs   &      r(   Ú_start_codex_device_coder„  õ  s’  é € ô   °ÀwÔO�F€CÜÔ*¨C¸ÕFÜ�~Š~Ó "Õ$€HÜ
�.Š.Ó
˜XÔ
%ß!Ö!Ü×#Ò# CÓ(ˆA÷ "ç�!—%‘%˜×$Ò$¨¨(­°yÔ(@ØÜ�mŠm˜CÓ × Ò ß	Ö	Ü×Ò  RÓ(ˆ÷ 
à‡u�uˆXƒ˜'Ô!ÝTÜ¨°A·E±E¸/Ó4J×4bÐ4bÐNbÔcˆØ"#§%¡%Ð(:Ó";×"FÐ"F¸wˆÔØˆ	Ø�5‰5�×ÒÜ¨Ð4hÔiÐià�c˜6 =°+¸qÀ½~ÐOaÐcdÐewÕcxØ”c˜!Ÿ%™% Ó-×4Ð4°Ó5°ÌÈAÏEÉEÐR\ÓL]×LbÐLbÐabÓHcðð ÷ "×!Ð!úò 	!ß	×	Ð	üsn   ‚A'HÁ)G,Â HÂHÂ'(HÃH ÃHÃ$HÃ<AHÄ>HÅ HÅ?A HÇ #HÇ$HÇ,G=	Ç7
HÈH	È	Hc                óh   € V ^8„  d   QhR\         \        ,          R\        \        \        3,          /# rK  rL  )r'   s   "r(   r)   r)     s&   € ÷ "ñ "¬h´s­mð "ÄÄSÌ#ÀXÅñ "r*   c              ƒ   óè  a
aaaa"  € ^ RI Ho
HpHpHo V! 4       w  poo\
        P                  ! R4      ;'       g    TP                  R4      o\        V
VVVV3R lRR7      G Rj  x€L
 pVP                  R4      pVe   \        V4      MRp\        VR	,          4      pVR
8”  d:   VR,          p\        ^ \        V\        P                  ! 4       ,
          4      4      p	M\        P                  ! 4       V,           pTp	\        RT \        \        V\!        VR,          4      VSSS
RWxR7	      \!        VR,          4      \!        VR,          4      T	\        ^T;'       g    RR,          4      4      #  EL	5i)rs   )ÚMINIMAX_OAUTH_CLIENT_IDÚMINIMAX_OAUTH_GLOBAL_BASEÚ_minimax_pkce_pairÚ_minimax_request_user_codeÚMINIMAX_PORTAL_BASE_URLrS  c                 ó   <€ S! V SSSSR 7      # ))r¤   r  rØ   Úcode_challengeÚstaterp   )r¤   r‡  rŠ  Ú	challenger  rŽ  s   &€€€€€r(   r$  Ú,_start_minimax_device_code.<locals>.<lambda>  s   ø€ Ñ3MØ ÐBYØ ¨õ4r*   T)Úfollow_redirectsNrÚ   Ú
expired_inl    J)£g     @�@r1  r•   r6  )	Úinterval_msr•   rò   rŽ  r  rØ   r5  Úexpired_in_rawrý   Úverification_uriiÐ  r  )rÝ   r‡  rˆ  r‰  rŠ  rm  rn  ro  r«   r/   r‘   rà   rb   r™   r   rC   r&   )rX   rˆ  r‰  Úverifierrá   Úinterval_rawr“  r”  Úexpires_at_tsÚexpires_in_secondsr‡  rŠ  r�  r  rŽ  s   &         @@@@@r(   Ú_start_minimax_device_coderš    sS  üé € ÷ó ñ "4Ó!5Ñ€Hˆi˜Ü—y’yÐ!:Ó;×XÐXÐ?X×`Ñ`ÐadÓe€OÜ#÷ %ð %ð ô÷ €Kð
 —?‘? :Ó.€LØ'3Ò'?”#�lÔ#ÀT€Kô ˜ \Õ2Ó3€NØÐ)Ô)Ø&¨Õ/ˆÜ  ¤C¨¼¿	º	»Õ(CÓ$DÓEÑäŸ	š	› nÕ4ˆØ+ÐÜ"Ø˜¤/ÜØ#¬s°;¸{Õ3KÓ/LÐ\dÐlqØ+Ð7NÐW_Ø)ô	
ô
 	ˆK˜Õ$Ó%¤s¨;Ð7IÕ+JÓ'KÐM_ÜˆA�×#Ð#˜t¨Õ,Ó-ó	ð 	ò#ùs   ‡AE2Á&E/Á'D	E2c                óh   € V ^8„  d   QhR\         \        ,          R\        \        \        3,          /# rK  rL  )r'   s   "r(   r)   r)   6  s&   € ÷ ñ ¬(´3­-ð ¼DÄÄcÀ½Nñ r*   c              ƒ   óÎ  "  € ^ RI Hp \        VRR7      G Rj  x€L
 p\        RT \        \        \        VR,          4      \        VR,          4      \        P                  ! 4       \        VR,          4      ,           R	7      \        VR
,          4      \        VP                  R4      ;'       g
    VR,          4      \        VR,          4      \        VR,          4      4      #  LÉ5i)rs   )Ú_xai_oauth_request_device_codeg      4@)rœ   Nr7  r“   rÚ   r�   )r“   rÚ   rý   r•   Úverification_uri_completer•  )
rÝ   r�  r«   r™   r   rC   r&   r‘   rb   r/   )rX   r�  rá   s   &  r(   Ú_start_xai_device_coderŸ  6  sµ   é € Ý>Ü#Ð$BÈDÔQ×Q€KÜ"Ø�WÔ0ÜÜ˜K¨Õ6Ó7Ä#ÀkÐR\ÕF]ÓB^Ü—y’y“{¤S¨°\Õ)BÓ%CÕCô	
ô 	ˆK˜Õ$Ó%ÜˆK�O‰OÐ7Ó8×[Ð[¸KÐHZÕ<[Ó\ÜˆK˜Õ%Ó&¬¨K¸
Õ,CÓ(Dó	ð 	ñ Rùs   ‚C%™C#šC
C%c                ót   € V ^8„  d   QhR\         R\        \         ,          R\        \         \        3,          /# )r"   rV   rX   r$   )r&   r   rC   r   )r'   s   "r(   r)   r)   K  s2   € ÷ "ñ "¬sð "¼XÄc½]ð "ÔVZÔ[^Ô`cÐ[cÕVdñ "r*   c              ƒ  ó‚   "  € \         P                  V 4      pVf   \        RRV  R2R7      hV! V4      G Rj  x€L
 #  L5i)zUHit the provider's device-auth endpoint, spawn its poller, return the display fields.Nrj  z	Provider z" does not support device-code flowr}  )Ú_DEVICE_CODE_STARTERSr/   r
   )rV   rX   Ústarters   && r(   Ú_start_device_code_flowr¤  K  sB   é € ä#×'Ñ'¨Ó4€GØ‚Ü¨°iÀ¸}ÐLnÐ4oÔpÐpÙ˜Ó!×!Ð!Ñ!ùs   ‚6?¸=¹?c                ó0   € V ^8„  d   QhR\         R\         /# )r"   Úplatformr$   rg   )r'   s   "r(   r)   r)   S  s   € ÷ ñ ¬cð ´cñ r*   c                óF   € V R8X  d   RpRV RV R2# RpV R8X  d   RV 2# V# )	zàHost-native command that removes Claude Code's borrowed credential file.

Windows must not emit ``rm -f``. PowerShell aliases ``rm`` to ``Remove-Item``,
and ``-f`` binds both ``-Force`` and ``-Filter`` (AmbiguousParameter).
Úwin32z!"$HOME/.claude/.credentials.json"zif (Test-Path -LiteralPath z) { Remove-Item -LiteralPath z -Force -ErrorAction Stop }z!rm -f ~/.claude/.credentials.jsonÚdarwinzKsecurity delete-generic-password -s "Claude Code-credentials" 2>/dev/null; rp   )r¦  ÚliteralÚrm_files   &  r(   Ú_claude_code_disconnect_commandr¬  S  sS   € ð �7ÔØ5ˆà)¨'¨ð 3(Ø(/ yÐ0LðNð	
ð 2€GØ�8ÔØ\Ð]dÐ\eÐfÐfØ€Nr*   c                óŠ   € V ^8„  d   QhR\         \        \        3,          R\        \        ,          R\        \        ,          /# )r"   r\   r¦  r$   ©rC   r&   r   r   )r'   s   "r(   r)   r)   e  s9   € ÷ Eñ EÜ”3œ�8�nðEÜ(0´­ðEäŒc…]ñEr*   c                ó¤   € V P                  R4      R8w  g   V P                  R4      R8w  d   R# \        T;'       g    \        P                  4      # )a  Shell command that clears an external provider's credentials, or None.

The disconnect API never silently deletes files another CLI owns; the GUI runs
this in its embedded terminal so the user sees exactly what executes. Claude Code
has no scriptable logout, so remove what logout would: the macOS Keychain entry
and/or ``~/.claude/.credentials.json`` (the two ``read_claude_code_credentials()`` sources).
``platform`` is the host the command will run on (default: this process). Pass it
explicitly in tests; do not fake ``sys.platform``.
rW   ÚexternalÚidzclaude-codeN)r/   r¬  Úsysr¦  )r\   r¦  s   &&r(   Ú"_oauth_provider_disconnect_commandr³  e  s?   € ð ‡|�|�FÓ˜zÔ)¨X¯\©\¸$Ó-?À=Ô-PÙÜ*¨8×+CÐ+C´s·|±|ÓDÐDr*   c                ó–   € V ^8„  d   QhR\         \        \        3,          R\         \        \        3,          R\        \        ,          /# )r"   r\   rS   r$   r®  )r'   s   "r(   r)   r)   v  s9   € ÷ ñ ¬d´3¼°8­nð ÄdÌ3ÔPSÈ8Ånð ÔYaÔbeÕYfñ r*   c                ó¸   € V P                  R4      R8X  d,   V P                  R4      R8w  d   \        V 4      '       d   R# R# VP                  R4      R8X  d   R	# R
# )zJReturn the manual disconnect path when the API cannot clear this provider.rW   r°  r±  Ú	anthropicuC   Managed outside Hermes â€” run the disconnect command to remove it.z0Managed by that provider's CLI; remove it there.r  Úenv_varu2   Remove the API key from Settings â†’ Keys instead.N)r/   r³  )r\   rS   s   &&r(   Ú_oauth_provider_disconnect_hintr¸  v  sM   € ð ‡|�|�FÓ˜zÔ)¨h¯l©l¸4Ó.@ÀKÔ.OÜ-¨h×7Ò7áXÙAØ‡z�z�(Ó˜yÔ(ÙCÙr*   c                ó\   € V ^8„  d   QhR\         \        \        \        3,          ,          /# rµ   )ÚlistrC   r&   r   )r'   s   "r(   r)   r)   †  s    € ÷ ñ œd¤4¬¬S¨¥>Õ2ñ r*   c                 ó,  € . p \        4       p\         FE  pVR,          V9  g   K  VP                  VR,          4       V P                  \	        V4      4       KG  	   ^ RIHp V! 4        F”  pVP                  R8w  g   VP                  V9   d   K'  VP                  VP                  4       T P                  RVP                  RVP                  RRRRVP                   2R	VP                  ;'       g    R
RR/4       K–  	  V #   \         d     T # i ; i)zúAccounts-tab provider list: ``_OAUTH_PROVIDER_CATALOG`` cards first (curated
order, win on metadata), then every other accounts-tab ``provider_catalog()`` entry
in ``hermes model`` order, so plugin-added OAuth/external providers appear automatically.r±  )Úprovider_catalogÚaccountsr~   rW   r°  Úcli_commandzhermes auth add Údocs_urlr.   rD  N)Úsetr   ÚaddÚappendrC   Úhermes_cli.provider_catalogr¼  ÚtabÚslugÚlabelÚ
signup_urlrA   )ÚrowsÚseenrF  r¼  Úds        r(   Ú_build_oauth_catalogrË  †  sò   € ð "$€DÜ“U€Dß(ˆØ��;˜dÖ"Ø�H‰H�U˜4•[Ô!Ø�K‰Kœ˜U›Ö$ñ )ðÝ@Ù!Ö#ˆAØ�u‰u˜
Ô" a§f¡f°¤nÙØ�H‰H�Q—V‘VÔØ�K‰KØ�a—f‘f˜f a§g¡g¨v°zØÐ!1°!·&±&°Ð:¸JÈÏÉ×HZÐHZÐXZÐ\gÐimðö ñ	 $ð €Køô ô ØØ€Kðús   ÁBD Ã4D ÄDÄDz/api/providers/oauthc                ó:   € V ^8„  d   QhR\         \        ,          /# )r"   rX   ©r   r&   )r'   s   "r(   r)   r)      s   € ÷ 1ñ 1¬´­ñ 1r*   c              ƒ  ó:   "  € R p\        W4      G Rj  x€L
 #  L5i)z›Every OAuth-capable provider with current status (token_preview is the last
N chars, never the full token; disconnect_command only for external providers).c                  óN  € . p \        4        F’  p\        VR ,          VP                  R4      4      p\        W4      pV P	                  R VR ,          RVR,          RVR,          R\        VR ,          VR,          4      RVR,          RVR\        V4      RVR	J R
V/	4       K”  	  RV /# )r±  rD  r~   rW   r¾  r¿  Údisconnect_hintÚdisconnect_commandÚdisconnectableNrS   Ú	providers)rË  rI  r/   r¸  rÂ  r   r³  )rÓ  ÚprS   rÐ  s       r(   Ú_runÚ"list_oauth_providers.<locals>._run£  s­   € Øˆ	Ü%Ö'ˆAÜ-¨a°­g°q·u±u¸[Ó7IÓJˆFÜ=¸aÓHˆOØ×ÑØ�a˜•g˜v q¨¥y°&¸!¸F½)ØÔ<¸Q¸t½WÀaÈÕFVÓWØ˜A˜j�MÐ+<¸oØ$Ô&HÈÓ&KØ  /°TÐ"9¸8ÀVðö ñ (ð ˜YÐ'Ð'r*   N)r   )rX   rÕ  s   & r(   Úlist_oauth_providersr×  Ÿ  s   é € ò(ô " 'Ó0×0Ð0Ñ0ùs   ‚”•c                óx   € V ^8„  d   QhR\         \        \        3,          R\         \        \        3,          RR/# )r"   r\   rS   r$   NrÕ   )r'   s   "r(   r)   r)   ´  s7   € ÷ pñ p¬D´´c°­Nð pÄDÌÌcÈÅNð pÐW[ñ pr*   c                 ó\   € \        W4      pV'       d   \        R V R,           RV 24      hR# )rj  r~   z' cannot be disconnected automatically. N)r¸  r
   )r\   rS   rÐ  s   && r(   Ú_reject_if_not_disconnectablerÚ  ´  s5   € Ü5°hÓG€OßÜ˜C H¨VÕ$4Ð#5Ð5\Ð]lÐ\mÐ!nÓoÐoñ r*   c                ó$   € V ^8„  d   QhR\         /# rµ   rU  )r'   s   "r(   r)   r)   º  s   € ÷ ñ œtñ r*   c                 ó<  € Rp  ^ RI Hp V! 4       pVP                  4       '       d   VP                  4        Rp  ^ RIHp T! R4      ;'       g    T p T #   \         d    \
        P                  R4       h i ; i  \         d    \
        P                  R4       h i ; i)zQClear only the Hermes-managed PKCE file and auth-store entry (never ~/.claude/*).F)Ú_get_hermes_oauth_fileTz&disconnect anthropic OAuth file failed)Úclear_provider_authr¶  z&disconnect anthropic auth store failed)	Úagent.anthropic_credentialsrÝ  ÚexistsÚunlinkrA   r±   Ú	exceptionrÝ   rÞ  )ÚclearedrÝ  Ú
oauth_filerÞ  s       r(   Ú_clear_anthropic_authrå  º  s™   € à€GðÝFÙ+Ó-ˆ
Ø×Ñ×ÒØ×ÑÔØˆGðÝ7Ù% kÓ2×=Ð=°gˆð €Nøô ô Ü�‰Ð?Ô@Øðûô ô Ü�‰Ð?Ô@Øðús!   „"A §A ºA9 ÁA9 Á"A6Á9"Bc                ó<   € V ^8„  d   QhR\         R\        R\        /# )r"   rL   Úprovider_namer$   )r‘   r&   r
   )r'   s   "r(   r)   r)   Ï  s&   € ÷ Añ A¬ð A¼Cð AÄMñ Ar*   c                 óB   € V R 8X  d   RV R2pMRV R2p\        WR7      # )é™  z'No stored credentials were removed for Ú.z(Failed to remove stored credentials for r}  )r
   )rL   rç  r?   s   && r(   Ú_disconnect_http_errorrë  Ï  s1   € Ø�cÔØ:¸=¸/ÈÐK‰à;¸M¸?È!ÐLˆÜ [Ô@Ð@r*   z"/api/providers/oauth/{provider_id}c                óR   € V ^8„  d   QhR\         R\        R\        \         ,          /# ©r"   rV   ÚrequestrX   ©r&   r   r   )r'   s   "r(   r)   r)   Ø  s(   € ÷ (1ñ (1´ð (1¼wð (1ÔQYÔZ]ÕQ^ñ (1r*   c              ƒ  óX   a "  € \        V4       V 3R lp\        W#4      G Rj  x€L
 #  L5i)zDDisconnect an OAuth provider. Token-protected (matches /env/reveal).c                  óz  <€ \        4        U u/ uF  q R ,          V bK  	  pp VP                  S4      pVf+   \        RRS RRP                  \	        V4      4       24      h\        V/ 4       \        V\        SVP                  R4      4      4       SR8X  dC    \        4       pT'       g   \        R
TR	,          4      h\        P                  RS4       RRRS/#  ^ RIHpHp V! S4      pSR8X  d   V! 4        V'       g   \        R
VR	,          4      h\        P                  RSV4       RRRS/# u up i   \         d    h \         d+    \        P                  RS4       \        RTR	,          4      hi ; i  \         d    h \         d+    \        P                  RS4       \        RTR	,          4      hi ; i)r±  rj  zUnknown provider: z. Available: z, rD  r¶  zdisconnect %s failedrË   r~   ré  zoauth/disconnect: %sÚokTr\   )rÞ  Ú!invalidate_nous_auth_status_cacher  z!oauth/disconnect: %s (cleared=%s))rË  r/   r
   rD   ÚsortedrÚ  rI  rå  rA   r±   râ  rë  r²   rÝ   rÞ  ró  )rÔ  Úcatalog_by_idr\   rã  rÞ  ró  rV   s         €r(   rÕ  Ú'disconnect_oauth_provider.<locals>._runÜ  s´  ø€ Ü-AÔ-CÓDÑ-C¨˜4� !šÑ-CˆÐDØ ×$Ñ$ [Ó1ˆØÒÜ Ð'9¸+¸ÀmÐTX×T]ÑT]Ô^dÐerÓ^sÓTtÐSuÐ%vÓwÐwä% h°Ô3Ü% hÔ0HÈÐV^×VbÑVbÐcnÓVoÓ0pÔqà˜+Ô%ðDÜ/Ó1�÷ Ü,¨S°(¸6Õ2BÓCÐCÜ�I‰IÐ,¨kÔ:Ø˜$ 
¨KÐ8Ð8ð	@ß^Ù)¨+Ó6ˆGØ˜fÔ$Ù1Ô3ßÜ,¨S°(¸6Õ2BÓCÐCÜ�I‰IÐ9¸;ÈÔPØ˜$ 
¨KÐ8Ð8ùò9 Eøô !ô ØÜô DÜ—‘Ð5°{ÔCÜ,¨S°(¸6Õ2BÓCÐCðDûô  ô 	ØÜô 	@Ü�N‰NÐ1°;Ô?Ü(¨¨h°vÕ.>Ó?Ð?ð	@ús/   ŽD2Â
D7 Ã%E: Ä/E: Ä7E7Å+E7Å:F:Æ+F:N)r   r   )rV   rî  rX   rÕ  s   f&& r(   Údisconnect_oauth_providerr÷  ×  s*   øé € ô �7Ôõ"@ôH " 'Ó0×0Ð0Ñ0ùs   ƒ *£(¤*c                ó   € V ^8„  d   QhRR/# ro   rp   )r'   s   "r(   r)   r)     s   € ÷ +ñ +˜Dñ +r*   c                  óV  € \         P                   ! 4       \        ,
          p \        ;_uu_ 4        \        P                  ! 4        UUu. uF  w  rVR ,          V 8  g   K  VNK  	  upp F  p\        P
                  ! VR4       K  	  RRR4       R# u uppi   + '       g   i     R# ; i)r]   N)rb   Ú_OAUTH_SESSION_TTL_SECONDSr   r   Úitemsri   )Úcutoffrc   rd   s      r(   Ú_gc_oauth_sessionsrý    sv   € Ü�YŠY‹[Ô5Õ5€Fß	Ö	Ü)8×)>Ò)>Ô)@Ô`Ñ)@™I˜CÀDÈÕDVÐY_ÑD_—C�CÑ)@Õ`ˆCÜ×Ò  TÖ*ñ a÷ 
Ñ	ùÛ`÷ 
×	Ð	ús#   ¯BÁB
ÁB
Á%"BÂBÂB(	c                óF   € V ^8„  d   QhR\         \        ,          R\        /# rK  rÍ  )r'   s   "r(   r)   r)     s   € ÷ ñ ¤X¬c¥]ð ´sñ r*   c                óB   € \        V 4      pV'       d   \        V4       V# )zVValidate the requested profile (404 via ``_resolve_profile_dir``) and return its name.)r   r   )rX   Úprofile_names   & r(   Ú_validate_oauth_profiler    s   € ä& wÓ/€LßÜ˜\Ô*ØÐr*   z(/api/providers/oauth/{provider_id}/startc                óR   € V ^8„  d   QhR\         R\        R\        \         ,          /# rí  rï  )r'   s   "r(   r)   r)     s&   € ÷ ñ ¬ð ´wð ÌÔRUÍñ r*   c              ƒ  óÀ  a "  € \        V4       \        4        \        V4       \        V 3R l\         4       R4      pVf   \        RRS  2R7      hVR,          R8X  d   \        RS  RVR	,           R
24      hVR,          R8w  d   \        RRR7      h\        S V4      G Rj  x€L
 p \        S VR7      G Rj  x€L
 pTe+   \        P                  ! \         YER,          4      G Rj  x€L
  T#  LJ L6  \         d]   p\        YF4      G Rj  x€L 
  \        T\
        4      '       d   h \        P                  RS 4       \        R\        T4      R7      hRp?ii ; i Lt5i)z.Initiate an OAuth login flow. Token-protected.c              3   óF   <"  € T F  qR ,          S8X  g   K  Vx € K  	  R# 5i)r±  Nrp   )r1   rÔ  rV   s   & €r(   r3   Ú$start_oauth_login.<locals>.<genexpr>   s   øé € ÐWÑ%< À$ÅÈ;Ñ@VŸ!š!Ó%<ùs   ƒ!—
!Nrj  zUnknown provider r}  rW   r°  z uses an external CLI; run `r¾  z
` manuallyr“   zUnsupported flowr”   zoauth/start %s failedrË   r[   )r   rý  r  rf  r   r
   Ú_begin_oauth_setup_metricr¤  rA   Ú_end_oauth_setup_metricrB   r±   râ  r&   r©   rª   rŒ   )rV   rî  rX   Úcatalog_entryrW   Úbodyr  s   f&&    r(   Ústart_oauth_loginr
    sA  øé € ô �7ÔÜÔÜ˜GÔ$ÜÔWÕ%<ÓWÐY]Ó^€MØÒÜ¨Ð6GÈÀ}Ð4UÔVÐVØ�VÕ 
Ô*Ü˜C K =Ð0LÈ]Ð[hÕMiÐLjÐjtÐ!uÓvÐvØ�VÕ Ô-Ü¨Ð4FÔGÐGÜ*¨;¸Ó@×@€Dð<Ü,¨[À'ÔJ×Jˆð ÒÜ×ÒÔ 2°D¸|Õ:LÓM×MÐMØ€Kñ AáJøÜô <Ü% dÓ.×.Ñ.Ü�aœ×'Ò'ØÜ�‰Ð.°Ô<Ü¨´C¸³FÔ;Ð;ûð<úñ 	Nùsa   ƒB EÂ#C.Â$EÂ)C2 Â9C0Â:C2 Â>)EÃ'EÃ(EÃ0C2 Ã2EÃ=EÄDÄAEÅEÅEc                óF   € V ^8„  d   QhR\         R\        \         ,          /# )r"   rV   rX   )r&   r   )r'   s   "r(   r)   r)   5  s   € ÷ ñ ´ð ¼xÌ½}ñ r*   c              ƒ  óâ   "  € ^ RI HpHp  \        V4      pV'       d   \	        V4      MRpV! V4      '       g   R# \
        P                  ! W V4      G Rj  x€L
 #  L  \         d     R# i ; i5i)z¾Start the provider-setup metric off the event loop (a cold metrics runtime blocks); None when the
owning profile does not collect. Never raises: the start route's own validation owns errors.)Úbegin_oauth_setupÚcollection_enabledN)rv   r  r  r   r   r©   rª   rA   )rV   rX   r  r  r   Úhomes   &&    r(   r  r  5  sb   é € ÷ dðÜ*¨7Ó3ˆß5AÔ# LÔ1ÀtˆÙ! $×'Ò'ÙÜ×&Ò&Ð'8ÀtÓL×LÐLÑLøÜô ÚðüsD   ‚	A/Œ-A ºA/¼A ÁAÁA ÁA/ÁA ÁA,Á(A/Á+A,Á,A/c                ó(   € V ^8„  d   QhR\         RR/# )r"   rÇ   r$   N)rA   )r'   s   "r(   r)   r)   C  s   € ÷ 	Pñ 	P¬Yð 	P¸4ñ 	Pr*   c              ƒ   ó‚  "  € V f   R # ^ RI HpHp \        P                  ! \
        4      ;_uu_ 4        \        V\        4      '       d   VP                  MR pRRRRRR/P                  V4      ;'       g	    V! V4      p\        P                  ! W RV4      G R j  x€L
  R R R 4       R #  L  + '       g   i     R # ; i5i)N)rŠ   r�  rÌ   r>  rÍ   r  ÚnetworkÚfailed)rv   rŠ   r�  rp  rs  rA   rB   r
   rL   r/   r©   rª   )rW   rÇ   rŠ   r�  rS   Úfailures   &&    r(   r  r  C  s˜   é € Ø‚|ÙßhÜ	×	Ò	œY×	'Õ	'ô %/¨s´M×$BÒ$B�—’ÈˆØ˜  V¨S°)Ð<×@Ñ@ÀÓH×dÐdÑL_Ð`cÓLdˆÜ×ÒÐ 5¸XÀwÓO×OÐO÷ 
(Ñ	'ñ
 	P÷ 
(×	'Ð	'üs5   ‚1B?³AB+Á6$B+ÂB)ÂB+Â
B?Â)B+Â+B<	Â6	B?z)/api/providers/oauth/{provider_id}/submitc          	      ó^   € V ^8„  d   QhR\         R\        R\        R\        \         ,          /# )r"   rV   r	  rî  rX   )r&   r   r   r   )r'   s   "r(   r)   r)   P  s7   € ÷ [ñ [Üð[Ü+ð[Ü6=ð[ÜHPÔQTÍñ[r*   c              ƒ  ó@   "  € \        V4       \        RRV  2R7      h5i)z5Submit the auth code for PKCE flows. Token-protected.rj  zsubmit not supported for r}  )r   r
   )rV   r	  rî  rX   s   &&&&r(   Úsubmit_oauth_coder  O  s$   é € ô
 �7ÔÜ
 CÐ2KÈKÈ=Ð0YÔ
ZÐZùs   ‚g      9@c          
      ó’   € V ^8„  d   QhR\         . \        3,          R\         \        .\        3,          R\        R\        R\        /# )r"   ÚreadÚchangedÚwaitÚtickr$   )r   r   r®   r�   )r'   s   "r(   r)   r)   ]  sF   € ÷ ñ œ8 B¬ GÕ,ð ´xÄÀÄtÀÕ7Lð ÔTYð Ôafð Ôknñ r*   c              ƒ  ór  "  € \         P                  ! 4       \        \        VR4      \        4      ,           pV ! 4       G Rj  x€L
 pV! V4      '       g\   V\         P                  ! 4       ,
          ;p^ 8”  d9   \
        P                  ! \        W64      4      G Rj  x€L
  V ! 4       G Rj  x€L
 pKi  V#  Lo L L5i)z�Re-run the async *read* every *tick* seconds until *changed* holds or *wait* (capped) runs out;
the last read is the answer. ``wait <= 0`` is one plain read.g        N)rb   ræ   Úminrà   Ú_LONG_POLL_CAP_SECONDSr©   rÄ   )r  r  r  r  rè   rH   Úlefts   &&&&   r(   Ú
_long_pollr!  ]  s   é € ô �~Š~Ó¤#¤c¨$°£nÔ6LÓ"MÕM€HÙ“&�L€EÙ�e�nŠn¨(´T·^²^Ó5EÕ*EÐ"E $ÈÔ!JÜ�mŠmœC ›OÓ,×,Ð,Ù“f—ŠØ€Lñ	 á,Ùùs<   ‚?B7ÁB1ÁB7ÁAB7ÂB3ÂB7Â(B5Â)	B7Â3B7Â5B7z4/api/providers/oauth/{provider_id}/poll/{session_id}c                ó^   € V ^8„  d   QhR\         R\         R\        \         ,          R\        /# )r"   rV   r[   rX   r  )r&   r   r�   )r'   s   "r(   r)   r)   i  s.   € ÷ ñ ¬#ð ¼3ð ÌÔRUÍð Ôejñ r*   c              ƒ  óÜ  a"  € \        V4      p\        ;_uu_ 4        \        P                  ! V4      oRRR4       S'       g   \	        RRR7      hSR,          V 8w  d   \	        RRR7      hSP                  R4      V8w  d   \	        RR	R7      hR
 V3R llp\        VR VRR7      G Rj  x€L
  RVRSR,          RSP                  R4      RSP                  R4      RSP                  R4      RSP                  R4      RSP                  R4      RSP                  R4      RSP                  R4      RSP                  R4      RSP                  R4      /#   + '       g   i     EL+; i L¾5i)uò   Poll a session's status (no auth â€” read-only state). One endpoint serves
every device-code flow: all report progress via the worker-updated ``status``.
With *wait* (seconds) it is a long-poll: it answers once the session leaves ``pending``.Nrå   zSession not found or expiredr}  r\   rj  zProvider mismatch for sessionrX   úOAuth session profile mismatchc                ó$   € V ^8„  d   QhR\         /# rµ   rg   )r'   s   "r(   r)   Ú(poll_oauth_session.<locals>.__annotate__w  s   € ÷ Lñ Lœ3ñ Lr*   c               “   óª   <"  € \         ;_uu_ 4        S P                  R 4      '       d   R MS R,          uuRRR4       #   + '       g   i     R# ; i5i)r°   rS   Nr\  rX  s   €r(   Ú_statusÚ#poll_oauth_session.<locals>._statusw  s1   øé € ß!Ö!Ø"&§(¡(¨;×"7Ò"7‘;¸TÀ(½^÷ "×!×!Ó!üs   ƒA’"?´A¿A	Á
	Ac                 ó   € V R 8g  # )r^   rp   rÒ   s   &r(   r$  Ú$poll_oauth_session.<locals>.<lambda>|  s	   € ¨V°yÒ-@r*   g      Ð?©r  r[   rS   r_   rý   ÚreasonÚaccount_emailÚmodelÚhandoffÚhandoff_statusÚ	retryableÚretry_after)r  r   r   r/   r
   r!  )rV   r[   rX   r  Úrequested_profiler(  rd   s   &&&&  @r(   Úpoll_oauth_sessionr5  h  sJ  øé € ô
 0°Ó8Ðß	Ö	Ü×"Ò" :Ó.ˆ÷ 
çÜ¨Ð4RÔSÐSØˆJÕ˜;Ô&Ü¨Ð4SÔTÐTØ‡x�x�	ÓÐ/Ô/Ü¨Ð4TÔUÐU÷Lð Lô
 �WÑ@À$ÈTÔ
R×RÐRà�j (¨D°­NØ˜Ÿ™ /Ó2°LÀ$Ç(Á(È<ÓBXð 	�$—(‘(˜8Ó$ o°t·x±xÀÓ7PÐRYÐ[_×[cÑ[cÐdkÓ[lð 	�4—8‘8˜IÓ&Ð(8¸$¿(¹(ÐCSÓ:Tà�T—X‘X˜kÓ*¨M¸4¿8¹8ÀMÓ;Rðð ÷ 
×	Ð	úñ Sùs/   ƒE,�E´E,ÁA'E,Â+E*Â,B*E,ÅE'	Å!
E,z!/api/providers/oauth/nous/handoffc                ót   € V ^8„  d   QhR\         R\        \        ,          R\        \        ,          R\        /# )r"   rî  rX   Úsincer  )r   r   r&   r�   )r'   s   "r(   r)   r)   Œ  s:   € ÷ [ñ [Üð[Ü'¬�}ð[Ü<DÄS½Mð[ÜX]ñ[r*   c              ƒ  óŒ   aaa"  € \        V 4       \        V4      oR R lo\        VV3R lV3R lVRR7      G Rj  x€L
 #  L5i)a  The profile's latest free-tier handoff (``guest_handoff.wire_status``). Token-protected. A
long-poll: given *since* (the ``updated_at`` the caller already shows) and *wait*, it answers once
the record changes. The keepalive retries a move in the background; this only reads.c                óF   € V ^8„  d   QhR\         \        \        3,          /# rµ   rÕ   )r'   s   "r(   r)   Ú)nous_handoff_status.<locals>.__annotate__•  s   € ÷ -ñ -”4œœS˜•>ñ -r*   c                  ó,   € ^ RI Hp Hp V! V ! 4       4      # )rs   ©r1  Úwire_status)Úhermes_cli.guest_handoffr1  r=  r<  s     r(   Ú_readÚ"nous_handoff_status.<locals>._read•  s   € ßHÙ™>Ó+Ó,Ð,r*   c                  ó   <€ \        SS 4      # r7   )r   )r?  r   s   €€r(   r$  Ú%nous_handoff_status.<locals>.<lambda>š  s   ø€ Ô'¨°eÔ<r*   c                 óD   <€ SR J ;'       g    V P                  R4      S8g  # )NÚ
updated_atr8   )rS   r7  s   &€r(   r$  rB  ›  s"   ø€ �u �}×IÐI¨¯
©
°<Ó(@ÀEÑ(IÐIr*   g      ð?r,  N)r   r  r!  )rî  rX   r7  r  r?  r   s   &&f&@@r(   Únous_handoff_statusrE  ‹  sG   úé € ô �7ÔÜ*¨7Ó3€Lõ-ô Ý<ÜIÈ4ÐVYô[÷ [ð [ñ [ùs   …8A½A¾Az*/api/providers/oauth/sessions/{session_id}c                óR   € V ^8„  d   QhR\         R\        R\        \         ,          /# )r"   r[   rî  rX   rï  )r'   s   "r(   r)   r)   Ÿ  s&   € ÷ 2ñ 2¬3ð 2¼ð 2Ì8ÔTWÍ=ñ 2r*   c              ƒ  ó¨  "  € \        V4       \        V4      p\        ;_uu_ 4        \        P                  ! V 4      pVe@   VP	                  R4      V8w  d   \        RRR7      hRVR&   \        P                  ! V R4       RRR4       Xf   RR	R
R/# ^ RIHp \        P                  ! WT4      G Rj  x€L
  RRRV /#   + '       g   i     LD; i L5i)a  Cancel a pending OAuth session. Token-protected.

Marks the session dict ``cancelled`` before popping it so a background
worker still holding that dict (e.g. the Codex poller) stops
polling/exchanging/saving instead of completing the login after the user
believed it was aborted.
NrX   rj  r$  r}  Tr°   rò  Fr;   zsession not foundrt   r[   )r   r  r   r   r/   r
   ri   rv   ru   r©   rª   )r[   rî  rX   r4  rd   ru   s   &&&   r(   Úcancel_oauth_sessionrH  ž  sÁ   é € ô �7ÔÜ/°Ó8Ðß	Ö	Ü×"Ò" :Ó.ˆØÒØ�x‰x˜	Ó"Ð&7Ô7Ü#°Ð<\Ô]Ð]Ø $ˆD�ÑÜ×Ò 
¨DÔ1÷ 
ð ‚|Ø�e˜YÐ(;Ð<Ð<åPÜ
×
Ò
Ð.Ó
5×5Ð5Ø�$˜ jÐ1Ð1÷ 
×	úñ 6ùs)   ‚%C§AB=Â1CÂ2CÂ3
CÂ=C	Ã	Cc                óø   € V ^8„  d   Qh/ ^ \         9   d
   \        ;R&   ^\         9   d
   \        ;R&   ^\         9   d>   \        \        \        \        \
        \        .\        3,          3,          3,          ;R&   # )r"   rç   r  rB  )Ú__conditional_annotations__r   rC   r&   rY   r   )r'   s   "r(   r)   r)      sk   € ÷ ñ ÷^ Ò ŒCÑ ñ_÷H Ò „sÑ ñI÷zò ”$”sœE¤#¤x´°¼°Õ'=Ð"=Õ>Ð>Õ?ñ ò{r*   r€  r7   )z
oauth-poll)r¸   )r.   )Nrs   )NNrs   )jrJ  Ú__doc__r©   rp  r   Úloggingrm  r`   r²  r�   rb   r   r   r   Útypingr   r   r   r   Úfastapir	   r
   r   Úhermes_cli.auth_constantsr   Úhermes_cli.web_depsr   r   Úhermes_cli.web_server_oauthr   r   r   r   r   Úhermes_cli.web_modelsr   Úhermes_cli.web_routers._commonr   r   Ú	getLoggerr±   Úrouterr   r   r   r   r   r   r   rÞ   rß   r  Úobjectrç   rú  rI   rT   re   rj   r…   rŒ   r™   r«   r³   r¼   rÈ   rÓ   râ   rì   rú   r  r  r  r  rB  rI  ry  r„  rš  rŸ  r¢  r¤  r¬  r³  r¸  rË  r/   r×  rÚ  rå  rë  Údeleter÷  rý  r  rÃ   r
  r  r  r  r  r!  r5  rE  rH  r)   )rJ  s   @r(   Ú<module>rX     s8  øðöó Û Û Û Û 	Û Û 
Û Û ß ,Ñ ,ß 0Ó 0ç 5Ñ 5å 0ß /÷õ õ 2ß Tà×ÒÐ0Ó1€Ù	‹€ñ Ð&Ð(HÓI€ÙÐ&Ó'€ÙÐ2Ð4TÓUÐ Ù#Ð$=Ð?\Ó]Ð ñ
 Ð2Ð4QÓRÐ ÙÐ(Ð*GÓH€ÙÐ.Ð0MÓNÐ à)€ØÐ!3Ð4€ØÐ Ù“(€
Ó Ø$Ð õ>õ$^÷(õ'÷gõ$õ÷
*÷(õkõõ*Võõ""õJnõ24,ñn ‹X€Ó ð af÷	õWð Ð)ñ ,Uð Vð Ð,ñ /ð ð Ð)ñ ,ð ð Ð5ñ 8ð ð Ð-ñ 0ð ð!CÐ ó õ. õ:@õFõ8"õJð  Ð# ^Ð5MØÐ/°Ð>TðÐ ÷"õ÷$Eõ"õ ð2 ‡�Ð"Ó#ö1ó $ð1õ(põõ*Að ‡�Ð3Ó4ö(1ó 5ð(1õf+õð ‡�Ð7Ó8öó 9ðõ4õ	Pð ‡�Ð8Ó9ö[ó :ð[ð Ð õð ‡�ÐBÓCöó DððD ‡�Ð/Ó0ö[ó 1ð[ð$ ‡�Ð;Ó<ö2ó =ò2r*   