Ë
    âß²jhD  ã                  ó  — d Z ddlmZ ddlZddlZddlZddlmZmZ ddlm	Z	m
Z
mZmZ ddlmZmZ ddlmZmZmZmZmZmZmZmZmZmZ ddlmZmZmZmZm Z   ejB                  d	«      Z"d%d
„Z#d&d'd„Z$dddœ	 	 	 	 	 	 	 	 	 	 	 	 	 d(d„Z%d)d*d„Z&d)d*d„Z'd&d+d„Z(d&d+d„Z)	 	 	 	 	 	 	 	 	 	 	 	 	 	 d,d„Z*d-d„Z+ddœd.d„Z,ddœ	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 d/d„Z-dddœ	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 d0d„Z.ddœd1d„Z/dded œ	 	 	 	 	 	 	 d2d!„Z0d3d"„Z1d4d#„Z2d5d$„Z3y)6a  Spotify OAuth (loopback PKCE) login, refresh and runtime credentials.

Re-exported from ``hermes_cli/auth.py`` (patch targets unchanged); origin helpers are imported
lazily per function so ``hermes_cli.auth.<helper>`` patches still intercept and no cycle forms.
é    )ÚannotationsN)ÚdatetimeÚtimezone)ÚAnyÚDictÚOptionalÚTuple)Ú	urlencodeÚurlparse)
Ú	AuthErrorÚ!DEFAULT_SPOTIFY_ACCOUNTS_BASE_URLÚDEFAULT_SPOTIFY_API_BASE_URLÚDEFAULT_SPOTIFY_REDIRECT_URIÚDEFAULT_SPOTIFY_SCOPEÚ)SPOTIFY_ACCESS_TOKEN_REFRESH_SKEW_SECONDSÚSPOTIFY_DASHBOARD_URLÚSPOTIFY_DOCS_URLÚ_spotify_errÚhttpx)Ú_bind_loopback_callback_serverÚ_make_loopback_callback_handlerÚ_pkce_code_challengeÚ_pkce_code_verifierÚ_serve_loopback_callbackzhermes_cli.authc                ó<   — t        | xs d«      j                  «       S )NÚ )ÚstrÚstrip)Úvalues    ú</home/ubuntu/.hermes/hermes-agent/hermes_cli/auth_spotify.pyÚ_cleanr!      s   € ÜˆuŠ{˜Ó×!Ñ!Ó#Ð#ó    c                óv   — dj                  t        j                  | xs t        j	                  «       «      «      S )zFRequested scope, whitespace-normalized and de-duplicated (order kept).ú )ÚjoinÚdictÚfromkeysr   Úsplit)Ú	raw_scopes    r    Ú_spotify_scope_stringr*      s)   € à�8‰8”D—M‘M 9Ò#EÔ0E×"LÑ"LÓ"NÓOÓPÐPr"   F)ÚexplicitÚstrip_slashc               óÒ   ‡	— ddl mŠ	 |gˆ	fd„|D «       ¢t        | t        «      r| j	                  |«      nd‘|‘­}|D ]&  }t        |«      }|r|j                  d«      }|sŒ$|c S  |S )zYFirst non-empty of explicit arg, env vars (``.env`` aware), stored state, then *default*.r   )Úget_env_valuec              3  ó.   •K  — | ]  } ‰|«      –— Œ y ­w©N© )Ú.0Úvarr.   s     €r    ú	<genexpr>z#_spotify_setting.<locals>.<genexpr>+   s   øè ø€ Ò;¨3‘M #×&Ñ;ùs   ƒNú/)Úhermes_cli.configr.   Ú
isinstancer&   Úgetr!   Úrstrip)
ÚstateÚ	state_keyÚenv_varsÚdefaultr+   r,   Ú
candidatesÚ	candidateÚcleanedr.   s
            @r    Ú_spotify_settingrA   $   s~   ø€ õ
 0àðÛ;°(Ô;ðä *¨5´$Ô 7ˆ�	‰	�)Ô¸TðàCJñ€Jð  ò ˆ	Ü˜Ó#ˆÙØ—n‘n SÓ)ˆGÚØŠNðð €Nr"   c                óB   — t        |ddd| ¬«      }|r|S t        dd«      ‚)NÚ	client_id)ÚHERMES_SPOTIFY_CLIENT_IDÚSPOTIFY_CLIENT_IDr   ©r+   zPSpotify client_id is required. Set HERMES_SPOTIFY_CLIENT_ID or pass --client-id.Úspotify_client_id_missing)rA   r   )r+   r:   rC   s      r    Ú_spotify_client_idrH   7   s7   € Ü Øˆ{ÐMÈrÐ\dô€Iñ ØÐÜ
ØZØ#óð r"   c                ó*   — t        |ddt        | ¬«      S )NÚredirect_uri)ÚHERMES_SPOTIFY_REDIRECT_URIÚSPOTIFY_REDIRECT_URIrF   )rA   r   )r+   r:   s     r    Ú_spotify_redirect_urirM   C   s   € ÜØˆ~ÐVÜ$¨xôð r"   c                ó*   — t        | ddt        d¬«      S )NÚapi_base_url)ÚHERMES_SPOTIFY_API_BASE_URLT©r,   )rA   r   ©r:   s    r    Ú_spotify_api_base_urlrS   J   s   € ÜØˆ~Ð?ÔA]Ðkoôð r"   c                ó*   — t        | ddt        d¬«      S )NÚaccounts_base_url)Ú HERMES_SPOTIFY_ACCOUNTS_BASE_URLTrQ   )rA   r   rR   s    r    Ú_spotify_accounts_base_urlrW   P   s   € ÜØÐ"Ð$IÔKlØôð r"   c           
     ó6   — t        | d|||d|dœ«      }|› d|› �S )NÚcodeÚS256)rC   Úresponse_typerJ   Úscoper:   Úcode_challenge_methodÚcode_challengez/authorize?)r
   )rC   rJ   r\   r:   r^   rU   Úquerys          r    Ú_spotify_build_authorize_urlr`   W   s8   € ô Ø°ÈØ ÀØ(ñó €Eð
  Ð  ¨E¨7Ð3Ð3r"   c                óâ   — t        | «      }|j                  xs d}|j                  dk7  rdn|dvrdn|j                  sdnd }|rt	        d|› �d«      ‚||j                  |j
                  xs d	fS )
Nr   Úhttpz.must use http://localhost or http://127.0.0.1.>   ú	127.0.0.1Ú	localhostz%must point to localhost or 127.0.0.1.z(must include an explicit localhost port.zSpotify PKCE redirect_uri Úspotify_redirect_invalidr5   )r   ÚhostnameÚschemeÚportr   Úpath)rJ   ÚparsedÚhostÚproblems       r    Ú_spotify_validate_redirect_urirm   c   s|   € Ü�lÓ#€FØ�?‰?Ò ˜b€Dà<B¿M¹MÈVÒ<SÑ8Ø8<ÐD^Ñ8^Ñ4Ø?E¿{º{Ñ7Øð	 ñ ÜÐ7¸°yÐAÐC]Ó^Ð^Ø�—‘˜fŸk™kÒ0¨SÐ0Ð0r"   ç     €f@©Útimeout_secondsc               ó�   — t        | «      \  }}}t        |d¬«      \  }}t        |||t        d¬«      }t	        |||t        d¬«      S )NÚSpotify)Údisplay_nameÚspotify_callback_bind_failed)ÚerrÚbind_failed_codeÚspotify_callback_timeout)rp   ru   Útimeout_code)rm   r   r   r   r   )rJ   rp   rk   rh   ri   Úhandler_clsÚresultÚservers           r    Ú_spotify_wait_for_callbackr|   q   sV   € Ü5°lÓCÑ€Dˆ$�Ü9¸$ÈYÔWÑ€K�Ü+Øˆd�K¤\ÐDbôd€Fä#Ø�¨¼\ÐXrôtð tr"   )Úprevious_statec               ó¤  — ddl m} t        j                  t        j
                  «      } || j                  dd«      «      }	t        j                  |j                  «       |	z   t        j
                  ¬«      }
t        |xs i «      }|j                  |||||t        | j                  d«      xs |«      j                  «       t        | j                  dd«      xs d«      xs dt        | j                  d«      «      t        | j                  d	«      xs |j                  d	«      «      |j                  «       |
j                  «       |	d
dœ«       |S )Nr   )Ú_coerce_ttl_secondsÚ
expires_in)Útzr\   Ú
token_typeÚBearerÚaccess_tokenÚrefresh_tokenÚ
oauth_pkce)rC   rJ   rU   rO   r\   Úgranted_scoper‚   r„   r…   Úobtained_atÚ
expires_atr€   Ú	auth_type)Úhermes_cli.authr   r   Únowr   Úutcr8   ÚfromtimestampÚ	timestampr&   Úupdater   r   r!   Ú	isoformat)Útoken_payloadrC   rJ   Úrequested_scoperU   rO   r}   r   rŒ   r€   r‰   r:   s               r    Ú_spotify_token_payload_to_stater”   z   s  € õ 4Ü
�,‰,”x—|‘|Ó
$€CÙ$ ]×%6Ñ%6°|ÀQÓ%GÓH€JÜ×'Ñ'¨¯©«¸*Ñ(DÌÏÉÔV€JÜ�Ò% 2Ó&€EØ	‡L�LØ°Ø.ÀØ Ü˜]×.Ñ.¨wÓ7ÒJ¸?ÓK×QÑQÓSÜ˜]×.Ñ.¨|¸XÓFÒRÈ(ÓSÒ_ÐW_Ü˜}×0Ñ0°Ó@ÓAÜ × 1Ñ 1°/Ó BÒ `ÀeÇiÁiÐP_ÓF`ÓaØ—}‘}“°j×6JÑ6JÓ6LØ ¨|ñ
ô 
ð €Lr"   r   )Úfailed_suffixÚrelogin_requiredc               óª  — 	 t        j                  | › d�ddi||¬«      }	|	j                  dk\  r8|	j
                  j                  «       }t        d|› d	|› �|rd
|› �ndz   ||¬«      ‚|	j                  «       }t        |t        «      rt        |j                  d«      «      st        |||¬«      ‚|S # t        $ r}
t        d|› d|
› �|«      |
‚d}
~
ww xY w)zZPOST to Spotify's ``/api/token`` and return the JSON payload, or raise a shaped AuthError.z
/api/tokenzContent-Typez!application/x-www-form-urlencoded)ÚheadersÚdataÚtimeoutzSpotify z	 failed: Ni�  z failed.z Response: r   ©Úreloginr„   )r   ÚpostÚ	Exceptionr   Ústatus_codeÚtextr   Újsonr7   r&   r!   r8   )rU   r™   rp   ÚwhatÚfailed_codeÚinvalid_codeÚinvalid_messager•   r–   ÚresponseÚexcÚdetailÚpayloads                r    Ú_spotify_token_postrª   ‘   só   € ðRÜ—:‘:Ø Ð! Ð,Ø#Ð%HÐIØØ#ô	
ˆð ×Ñ˜sÒ"Ø—‘×$Ñ$Ó&ˆÜØ�t�f˜H ] OÐ4ÑRX¸+ÀfÀXÑ8NÐ^`ÑaØÐ!1ô
ð 	
ð �m‰m‹o€GÜ�gœtÔ$¬F°7·;±;¸~Ó3NÔ,OÜ˜?¨LÐBRÔSÐSØ€Nøô ò RÜ˜X d V¨9°S°EÐ:¸KÓHÈcÐQûðRús   ‚B1 Â1	CÂ:CÃCç      4@c               ó>  — t        | j                  d«      «      }|st        ddd¬«      ‚t        | ¬«      }t	        | «      }t        |d||dœ|dd	d
ddd¬«	      }t        ||t        | ¬«      t        | j                  d«      xs t        «      |t        | «      | ¬«      S )Nr…   z?Spotify refresh token missing. Run `hermes auth spotify` again.Úspotify_refresh_token_missingTr›   rR   )Ú
grant_typer…   rC   ztoken refreshÚspotify_refresh_failedÚspotify_refresh_invalidz9Spotify refresh response did not include an access_token.z! Run `hermes auth spotify` again.)rp   r¢   r£   r¤   r¥   r•   r–   r\   )rC   rJ   r“   rU   rO   r}   )r!   r8   r   rH   rW   rª   r”   rM   r   r   rS   )r:   rp   r…   rC   rU   r©   s         r    Ú_refresh_spotify_oauth_stater±   ­   s±   € Ü˜5Ÿ9™9 _Ó5Ó6€MÙÜØMØ+°Tô
ð 	
ô
 #¨Ô/€IÜ2°5Ó9ÐÜ!ØØ&¸ÐU^Ñ_Ø'¨oÐKcØ.ØSØ9ÈDô€Gô +Ø˜9Ô3HÈuÔ3UÜ˜EŸI™I gÓ.ÒGÔ2GÓHØ+Ô:OÐPUÓ:VØô	ð r"   T)Úforce_refreshÚrefresh_if_expiringÚrefresh_skew_secondsc                ó¬  — ddl m}m}m}m}m}m}m}	m}
  |«       5   |«       } ||d«      }|st        ddd¬«      ‚t        | «      }|s|r ||j                  d«      |«      }|r	  ||«      } |
|d|d	¬
«        |	|«       d d d «       t#        j                  d«      «      }|st        ddd¬«      ‚d||t%        |j                  dd«      xs d«      t'        |«      t#        |j                  d«      xs |j                  d«      «      t)        |¬«      t+        |¬«      |j                  d«      t#        |j                  d«      «      dœ
S # t        $ ro}|j                  r]|j                  d«      rL ||d|«       	  |
|d|d	¬
«        |	|«       ‚ # t        $ r }t        j!                  d|«       Y d }~‚ d }~ww xY w‚ d }~ww xY w# 1 sw Y   �ŒHxY w)Nr   )Ú_auth_store_lockÚ_is_expiringÚ_load_auth_storeÚ_load_provider_stateÚ_quarantine_flat_oauth_stater±   Ú_save_auth_storeÚ_store_provider_stateÚspotifyz>Spotify is not authenticated. Run `hermes auth spotify` first.Úspotify_auth_missingTr›   r‰   F©Ú
set_activer…   z6Spotify OAuth: failed to persist quarantined state: %sr„   z>Spotify access token missing. Run `hermes auth spotify` again.Úspotify_access_token_missingr‚   rƒ   r‡   r\   rR   )
Úproviderr„   Úapi_keyr‚   Úbase_urlr\   rC   rJ   r‰   r…   )r‹   r¶   r·   r¸   r¹   rº   r±   r»   r¼   r   Úboolr8   r   r–   rž   ÚloggerÚdebugr!   r   rS   rH   rM   )r²   r³   r´   r¶   r·   r¸   r¹   rº   r±   r»   r¼   Ú
auth_storer:   Úshould_refreshr§   Ú	_save_excr„   s                    r    Ú#resolve_spotify_runtime_credentialsrË   È   sÙ  € ÷ L÷  Ló  LÙ	Ó	ñ Ù%Ó'ˆ
Ù$ Z°Ó;ˆÙÜØPÐRhÐrvôð ô ˜mÓ,ˆÙÑ"5Ù)¨%¯)©)°LÓ*AÐCWÓXˆNÙðÙ4°UÓ;�Ù% j°)¸UÈuÕUÙ  Ô,÷ô4 ˜%Ÿ)™) NÓ3Ó4€LÙÜØLØ*°Dô
ð 	
ð ¨|ÈÜ˜%Ÿ)™) L°(Ó;ÒG¸xÓHÜ)¨%Ó0Ü˜Ÿ	™	 /Ó2ÒH°e·i±iÀÓ6HÓIÜ'¨eÔ4Ü-°EÔ:È%Ï)É)ÐT`ÓJaÜ §	¡	¨/Ó :Ó;ñð øô# ò Ø×'Ò'¨E¯I©I°oÔ,FÙ0°¸	À3ÔGðjÙ-¨j¸)ÀUÐW\Õ]Ù(¨Ô4ð øô %ò jÜŸ™Ð%]Ð_h×iÐiØûðjúàûðú÷!ñ úsT   œA
G	Á'EÅ	GÅ'GÅ?FÆGÆ	F=ÆF8Æ3GÆ8F=Æ=GÇGÇG	Ç	Gc            
     ó”  — ddl m} m}  |d«      }|sddiS |j                  d«      }t	        |j                  d«      «      }t        |xs
  | |d«       «      |j                  dd	«      |j                  d
«      |j                  d«      |j                  d«      xs |j                  d«      ||j                  d«      t        |«      dœS )Nr   )r·   Úget_provider_auth_stater½   Ú	logged_inFr‰   r…   rŠ   r†   rC   rJ   r‡   r\   rO   )rÎ   rŠ   rC   rJ   r\   r‰   rO   Úhas_refresh_token)r‹   r·   rÍ   r8   r!   rÅ   )r·   rÍ   r:   r‰   r…   s        r    Úget_spotify_auth_statusrÐ   ù   sµ   € ßEÙ# IÓ.€EÙØ˜UÐ#Ð#à—‘˜<Ó(€JÜ˜5Ÿ9™9 _Ó5Ó6€Mä˜-ÒJ©|¸JÈÓ/JÐ+JÓKØ—Y‘Y˜{¨LÓ9ÈÏ	É	ÐR]ÓH^ØŸ	™	 .Ó1Ø—‘˜?Ó+ÒA¨u¯y©y¸Ó/AÐQ[ØŸ	™	 .Ó1ÌÈ]ÓH[ñð r"   c                óÞ  — ddl m} ddlm} t	        dd› dd› dt
        › dt        › d	| › d
�«        |«       s	 t        j                  t        «       ddl
m} 	  |d«      j                  «       }|st	        dt
        › d�«       t        d«      ‚ |d|«       | r| t         k7  r	 |d| «       t	        d«       |S # t        $ r Y Œrw xY w# t        t        f$ r t	        «        t        d«      ‚w xY w)z`Walk the user through creating a Spotify developer app; persist the client_id to ~/.hermes/.env.r   )Ú_is_remote_session)Úsave_env_valueú
zF======================================================================z
Spotify first-time setup
z£

Spotify requires every user to register their own lightweight
developer app. This takes about two minutes and only has to be
done once per machine.

Full guide: z

Steps:
  1. Opening zž in your browser...
  2. Click 'Create app' and fill in:
       App name:     anything (e.g. hermes-agent)
       Description:  anything
       Redirect URI: z’
       API/SDK:      Web API
  3. Agree to the terms, click Save.
  4. Open the app's Settings page and copy the Client ID.
  5. Paste it below.
)Ú
line_inputzSpotify Client ID: zSpotify setup cancelled.z
No Client ID entered. See z for the full guide.z)Spotify setup cancelled: empty Client ID.rD   rK   z2
Saved HERMES_SPOTIFY_CLIENT_ID to ~/.hermes/.env
)r‹   rÒ   r6   rÓ   Úprintr   r   Ú
webbrowserÚopenrž   Úhermes_cli.cli_outputrÕ   r   ÚEOFErrorÚKeyboardInterruptÚ
SystemExitr   )Úredirect_uri_hintrÒ   rÓ   rÕ   Úraws        r    Ú_spotify_interactive_setuprß   
  s  € å2Ý0Ü	Ø
ˆXˆJÐ2°8°*ð =ô (Ð(ð )ä-Ð.ð / ð !2Ð2ð 3!ð	!ôñ$ Ôð	Ü�O‰OÔ1Ô2õ 1ð5ÙÐ.Ó/×5Ñ5Ó7ˆñ
 ÜÐ,Ô-=Ð,>Ð>RÐSÔTÜÐDÓEÐEñ Ð-¨sÔ3ÙÐ.Ô2NÒNÙÐ4Ð6GÔHä	Ð
@ÔAØ€Jøô) ò 	Ùð	ûô Ô'Ð(ò 5ÜŒÜÐ3Ó4Ð4ð5ús   ¸B8 ÁC Â8	CÃCÃ%C,c                ót  — ddl m}m}m}m}m}m}m}m}  |d«      xs i }		 t        t        | dd «      |	«      }
t        t        | dd «      |	«      }t        t        | d
d «      xs |	j!                  d
«      «      }t#        |	«      }t%        |	«      }t        | dd«       }t'        «       }t)        j*                  «       j,                  }t/        |
|||t1        |«      |¬«      }t3        d|
› d|› d|› dt4        › d�	«        ||t4        ¬«       |r3 |«       s, |«       r%	 t7        j8                  |«      }t3        |rdnd«       t=        |t?        t        | dd «      xs d«      ¬«      }|j!                  d«      r$tA        d|j!                  d«      xs |d   › �«      ‚|j!                  d«      |k7  rtA        d«      ‚tC        ||
dtE        |j!                  d«      xs d«      ||dœt?        t        | dd «      xs d «      d!d"d#d$¬%«      }tG        ||
||||¬&«      } |«       5   |«       } ||d|d¬'«        ||«      }d d d «       t3        d(› d)t4        › �«       y # t        $ r;}t        |dd«      dk7  r‚ t        t        | dd «      xs t        ¬	«      }
Y d }~�Œ[d }~ww xY w# t:        $ r d}Y �Œ{w xY w# 1 sw Y   ŒxxY w)*Nr   )r¶   Ú_can_open_graphical_browserrÒ   r¸   Ú_print_loopback_ssh_hintr»   r¼   rÍ   r½   rC   rY   r   rG   rJ   )rÝ   r\   Ú
no_browserF)rC   rJ   r\   r:   r^   rU   z*Starting Spotify PKCE login...
Client ID: z
Redirect URI: zo
Make sure this redirect URI is allow-listed in your Spotify app settings.

Open this URL to authorize Hermes:
z

Full setup guide: rÔ   )Údocs_urlz)Browser opened for Spotify authorization.z<Could not open the browser automatically; use the URL above.rš   rn   ro   ÚerrorzSpotify authorization failed: Úerror_descriptionr:   z-Spotify authorization failed: state mismatch.Úauthorization_code)rC   r®   rY   rJ   Úcode_verifierr«   ztoken exchangeÚspotify_token_exchange_failedÚspotify_token_exchange_invalidz7Spotify token response did not include an access_token.)rp   r¢   r£   r¤   r¥   )rC   rJ   r“   rU   rO   r¿   z(Spotify login successful!
  Auth state: z8
  Provider state saved under providers.spotify
  Docs: )$r‹   r¶   rá   rÒ   r¸   râ   r»   r¼   rÍ   rH   Úgetattrr   rß   r   rM   r*   r8   rW   rS   r   ÚuuidÚuuid4Úhexr`   r   rÖ   r   r×   rØ   rž   r|   ÚfloatrÜ   rª   r   r”   )Úargsr¶   rá   rÒ   r¸   râ   r»   r¼   rÍ   Úexisting_staterC   r§   rJ   r\   rU   rO   Úopen_browserrè   Ústate_nonceÚauthorize_urlÚopenedÚcallbackr’   Úspotify_staterÈ   Úsaved_tos                             r    Úlogin_spotify_commandrù   :  sñ  € ÷ P÷  Pó  PÙ,¨YÓ7Ò=¸2€Nð
Ü&¤w¨t°[À$Ó'GÈÓXˆ	ô )¬°°~ÀtÓ)LÈnÓ]€LÜ!¤'¨$°¸Ó">Ò"]À.×BTÑBTÐU\ÓB]Ó^€EÜ2°>ÓBÐÜ(¨Ó8€LÜ˜t \°5Ó9Ð9€Lä'Ó)€MÜ—*‘*“,×"Ñ"€KÜ0Ø¨,¸eÈ;Ü+¨MÓ:ÐN_ô€Mô
 
Ø
5°i°[Ð@PÐQ]ÐP^ð _/à/<¨oÐ=SÔTdÐSeÐegð	iôñ ˜\Ô4DÕEáÑ.Ô0Ñ5PÔ5Rð	Ü—_‘_ ]Ó3ˆFô 	Ù;AÑ7ØOô	
ô
 *¨,ÌÌgÐVZÐ\eÐgkÓNlÒNuÐpuÓHvÔw€HØ‡|�|�GÔÜÐ9¸(¿,¹,ÐGZÓ:[Ò:pÐ_gÐhoÑ_pÐ9qÐrÓsÐsØ‡|�|�GÓ Ò+ÜÐHÓIÐIä'Øà"Ð2FÜ˜Ÿ™ VÓ,Ò2°Ó3À\Ø*ñ	
ô
 œg d¨I°tÓ<ÒDÀÓEØÐ+JØ5ØQô€Mô 4Ø ¸ÐW\Ø+¸,ô€Mñ
 
Ó	ñ 0Ù%Ó'ˆ
Ù˜j¨)°]ÈuÕUÙ# JÓ/ˆ÷0ô
 
Ø
3°H°:ð >CÜCSÐBTð	VõøôE ò 
Ü�3˜ Ó#Ð'BÒBØÜ.Ü% d¨N¸DÓAÒaÔEaô
Ž	ûð
ûô> ò 	Ø‹Fð	ú÷<0ð 0ús5   ¢I ÄJ ÈJ.É	JÉ0JÊJÊJ+Ê*J+Ê.J7)r   r   Úreturnr   r0   )r)   úOptional[str]rú   r   )r:   úOptional[Dict[str, Any]]r;   r   r<   zTuple[str, ...]r=   r   r+   rû   r,   rÅ   rú   r   )NN)r+   rû   r:   rü   rú   r   )r:   rü   rú   r   )rC   r   rJ   r   r\   r   r:   r   r^   r   rU   r   rú   r   )rJ   r   rú   ztuple[str, int, str])rJ   r   rp   rï   rú   zdict[str, Any])r’   úDict[str, Any]rC   r   rJ   r   r“   r   rU   r   rO   r   r}   rü   rú   rý   )rU   r   r™   zDict[str, str]rp   rï   r¢   r   r£   r   r¤   r   r¥   r   r•   r   r–   rÅ   rú   rý   )r:   rý   rp   rï   rú   rý   )r²   rÅ   r³   rÅ   r´   Úintrú   rý   )rú   rý   )rÝ   r   rú   r   )rú   ÚNone)4Ú__doc__Ú
__future__r   Úloggingrì   r×   r   r   Útypingr   r   r   r	   Úurllib.parser
   r   Úhermes_cli.auth_constantsr   r   r   r   r   r   r   r   r   r   Úhermes_cli.auth_device_flowr   r   r   r   r   Ú	getLoggerrÆ   r!   r*   rA   rH   rM   rS   rW   r`   rm   r|   r”   rª   r±   rË   rÐ   rß   rù   r1   r"   r    ú<module>r     s  ðñõ #ã Û Û ß 'ß -Ó -ß ,÷÷ ÷ ÷
3õ 3ð 
ˆ×	Ñ	Ð,Ó	-€ó$ôQð #¸ñØ#ðØ03ðØ?NðØY\ðàðà15ðð 	óô&	ôôôð	4Øð	4Ø%(ð	4Ø14ð	4Ø=@ð	4ØRUð	4àð	4ð 	ó	4ó1ð OTõ tð [_ñØ!ðØ14ðØDGðØZ]ðàðà*-ðà?Wðð óð2 UWØ"ñØðØ"0ðØFKðØSVðàðà$'ðà:=ðàNQðð ðð ó	ð8 UYõ ð8 #ÀØ Iñ.Øð.Ø9=ð.àð.ð ó.óbó"-ô`Lr"   