+
    „WÝjá  ã                  óÊ   € R t ^ RIHt ^ RIt^ RIt^ RI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HtHtHtHtHt RtRR	/R
 R lltR R ltR R ltRRRR/R R lltR# )u_  OpenRouter OAuth PKCE login (``hermes auth add openrouter --type oauth``).

Contract: https://openrouter.ai/docs/guides/overview/auth/oauth. The browser is sent to
``/auth?callback_url=...&code_challenge=...&code_challenge_method=S256``; the redirect carries
``?code=``; ``POST /api/v1/auth/keys`` swaps ``{code, code_verifier, code_challenge_method}`` for
``{"key": "sk-or-v1-..."}`` â€” a plain user-controlled API key, no refresh token. OpenRouter echoes no
``state`` parameter, so the CSRF nonce rides in the loopback callback PATH: a redirect to any other
path is a 404 and never reaches the exchange.
)ÚannotationsN)ÚAnyÚDict)Ú	urlencode)ÚOPENROUTER_AUTH_KEYS_URLÚOPENROUTER_AUTH_URLÚOPENROUTER_OAUTH_DOCS_URLÚ_openrouter_errÚhttpx)Ú_bind_loopback_callback_serverÚ_can_open_graphical_browserÚ_is_remote_sessionÚ_make_loopback_callback_handlerÚ_pkce_code_challengeÚ_pkce_code_verifierÚ_serve_loopback_callbacki   Útimeout_secondsg      4@c               ó(   € V ^8„  d   QhRRRRRRRR/# )é   ÚcodeÚstrÚcode_verifierr   ÚfloatÚreturn© )Úformats   "ÚNC:\Users\johnn\AppData\Local\hermes\hermes-agent\hermes_cli\auth_openrouter.pyÚ__annotate__r      s*   € ÷ ñ  Cð ¸ð ÐQVð Ðbeñ ó    c          	     óÌ  €  \         P                  ! \        RV RVRR/RR/VR7      pTP
                  R8X  d   \	        RRRR7      hTP
                  R8¼  d[   TP                  P                  4       R
\         p\	        RTP
                   R2T'       d   RT 2,           R	4      hR,           R	4      h TP                  4       p\        T\        4      '       d3   \        TP                  R4      ;'       g    R4      P                  4       MRpT'       g   \	        RR4      hT#   \         d   p\	        RT 2R	4      ThR
p?ii ; i  \         d   p\	        RR4      ThR
p?ii ; i)z\Exchange the authorization code for an API key; the key never enters a log or error message.r   r   Úcode_challenge_methodÚS256zContent-Typezapplication/json)ÚjsonÚheadersÚtimeoutz!OpenRouter code exchange failed: Ú openrouter_token_exchange_failedNi“  zrOpenRouter rejected the authorization code (invalid, already used, or older than 10 minutes). Run the login again.Ú openrouter_token_exchange_deniedT)Úrelogini�  z&OpenRouter code exchange failed (HTTP z).z Response: Ú z2OpenRouter code exchange returned a non-JSON body.Ú!openrouter_token_exchange_invalidÚkeyz:OpenRouter code exchange response did not include a 'key'.)r
   Úpostr   Ú	Exceptionr	   Ústatus_codeÚtextÚstripÚ_ERROR_BODY_LIMITr"   Ú
ValueErrorÚ
isinstanceÚdictr   Úget)r   r   r   ÚresponseÚexcÚdetailÚpayloadr*   s   &&$     r   Ú_openrouter_exchange_coder9      s’  € ðvÜ—:’:Ü$Ø˜˜o¨}Ð>UÐW]ð,_à#Ð%7Ð8À/ôSˆð ×Ñ˜sÔ"Üð#Ø$FÐPTôVð 	Vð ×Ñ˜sÔ"Ø—‘×$Ñ$Ó&Ð'9Ô(9Ð:ˆÜØ4°X×5IÑ5IÐ4JÈ"ÐM×kqÐS^Ð_eÐ^fÐQgÕzØ.ó0ð 	0ØwyÕzØ.ó0ð 	0ðpØ—-‘-“/ˆô 4>¸gÄt×3LÒ3LŒ#ˆg�k‰k˜%Ó ×&Ð& BÓ
'×
-Ñ
-Ô
/ÐRT€CßÜØHÐJmóoð 	oà€Jøô+ ô vÜÐ AÀ#ÀÐGÐIkÓlÐruÐuûðvûô ô pÜØ@ÐBeógØloð	pûðpús/   ‚&D# Â3E Ä#EÄ.D>Ä>EÅE#ÅEÅE#c               ó    € V ^8„  d   QhRRRR/# )r   Úauth_urlr   r   r   )r   s   "r   r   r   :   s   € ÷ 	ñ 	¨ð 	°ñ 	r   c                ó„   € ^ RI Hp \        RV  R24       V! R4      P                  4       pV'       g   \	        RR4      hV# )zeRemote/SSH: OpenRouter shows the code on screen when ``callback_url`` is omitted; the user pastes it.)Úmasked_secret_promptu‘   Remote session detected â€” using OpenRouter's headless flow.
Open this URL in a browser on any machine, authorize, then paste the code shown:
  Ú
zAuthorization code: zNo authorization code entered.Úopenrouter_auth_no_code)Úhermes_cli.secret_promptr=   Úprintr/   r	   )r;   r=   r   s   &  r   Ú_openrouter_headless_coderB   :   sP   € å=Ü	ð	_Ø_gÐ^hÐhjð	lômñ  Ð 6Ó7×=Ñ=Ó?€DßÜÐ>Ð@YÓZÐZØ€Kr   c               ó(   € V ^8„  d   QhRRRRRRRR/# )	r   Úauth_url_paramszdict[str, str]Úopen_browserÚboolr   r   r   r   r   )r   s   "r   r   r   F   s+   € ÷ ñ ¨~ð ÐPTð Ðglð Ðqtñ r   c               ó  € \         P                  ! ^4      pRV 2p\        VRR7      w  rV\        R^ V\        RR7      pRVP
                  ^,           V 2p\         R\        R	V/V C4       2p	\        R
V	 R\         24       V'       d=   \        4       '       d-    \        P                  ! V	4      p
\        V
'       d   RMR4       \        R4       \        WvV\        RR7      pVP                  R4      '       d0   \	        RVP                  R4      ;'       g
    VR,           2R4      h\!        VP                  R4      ;'       g    R4      P#                  4       pV'       g   \	        RR4      hV#   \         d    Rp
 LÐi ; i)é   z
/callback/Ú
OpenRouter)Údisplay_namez	127.0.0.1Úopenrouter_callback_bind_failed)ÚerrÚbind_failed_codezhttp://127.0.0.1:Ú?Úcallback_urlz5Open this URL to authorize Hermes with OpenRouter:
  z

Docs: Fz,Browser opened for OpenRouter authorization.z<Could not open the browser automatically; use the URL above.z&Waiting for the OpenRouter callback...Úopenrouter_callback_timeout)r   rL   Útimeout_codeÚerrorz!OpenRouter authorization failed: Úerror_descriptionÚopenrouter_auth_deniedr   r(   z8OpenRouter callback did not carry an authorization code.r?   )ÚsecretsÚtoken_urlsafer   r   r	   Úserver_addressr   r   rA   r   r   Ú
webbrowserÚopenr,   r   r4   r   r/   )rD   rE   r   ÚnonceÚpathÚhandler_clsÚresultÚserverÚredirect_urir;   ÚopenedÚcallbackr   s   &$$          r   Ú_openrouter_loopback_coderb   F   s�  € Ü×!Ò! "Ó%€EØ˜�wÐ€DÜ9¸$È\ÔZÑ€KÜ+Ø�Q˜¬ÐKlôn€Fà& v×'<Ñ'<¸QÕ'?Ð&@ÀÀÐG€LÜ%Ð& a¬	°>À<Ð2cÐSbÐ2cÓ(dÐ'eÐf€Hä	ÐBÀ8À*ÈJÔWpÐVqÐ
rÔsßÔ3×5Ò5ð	Ü—_’_ XÓ.ˆFô 	ÇÑ<ØQô	Sä	Ð
2Ô3Ü'Ø¨¼_Ø2ô4€Hð ‡|�|�G×ÒÜØ/°·±Ð=PÓ0Q×0fÐ0fÐU]Ð^eÕUfÐ/gÐhØ$ó&ð 	&ô ˆx�|‰|˜FÓ#×)Ð) rÓ*×0Ñ0Ó2€DßÜÐXÐZsÓtÐtØ€Køô ô 	ØŠFð	ús   ÂE4 Å4FÆFrE   Tg     Àr@c               ó$   € V ^8„  d   QhRRRRRR/# )r   rE   rF   r   r   r   zdict[str, Any]r   )r   s   "r   r   r   e   s'   € ÷ 	Gñ 	G¨Dð 	GÈ%ð 	GÐ\jñ 	Gr   c           	     óæ   € \        4       pR\        V4      RR/p\        4       '       d%   \        \         R\        / VCRR/C4       24      pM\        W0VR7      p\        R4       R	\        WB4      /# )
zSRun the PKCE flow and return ``{"api_key": ...}`` for the credential-pool add path.Úcode_challenger    r!   rN   Ú	key_labelzhermes-agent)rE   r   z>Exchanging the authorization code for an OpenRouter API key...Úapi_key)	r   r   r   rB   r   r   rb   rA   r9   )rE   r   r   Úparamsr   s   $$   r   Ú_openrouter_pkce_loginri   e   s|   € ä'Ó)€MØÔ 4°]Ó CÐE\Ð^dÐe€FÜ×ÒÜ(Ô,?Ð+@ÀÄ)ÐLsÈvÐLsÐWbÐdrÑLsÓBtÐAuÐ)vÓw‰ä(¨Ð\kÔlˆÜ	Ð
JÔKØÔ0°ÓEÐFÐFr   )Ú__doc__Ú
__future__r   rU   rX   Útypingr   r   Úurllib.parser   Úhermes_cli.auth_constantsr   r   r   r	   r
   Úhermes_cli.auth_device_flowr   r   r   r   r   r   r   r0   r9   rB   rb   ri   r   r   r   Ú<module>rp      su   ðñõ #ã Û ß Ý "÷fõ f÷j÷ jñ jð Ð ðÐY]÷ õ>	õð>	G°4ð 	GÐRW÷ 	Gñ 	Gr   