+
    Ki?&                       R t ^ RIHt ^ RIt^ RIt^ RIt^ RIt^ RIt^ RIt^ RI	H
t
 ^ RIHt ]P                  ! ]4      tRtRtRtRtR	tR
tR!tR"t^t^tR R ltR R ltR R ltR R ltR R ltRRRR/R R lltRRRR/R R  llt R# )#u  GitHub Copilot authentication utilities.

Implements the OAuth device code flow used by the Copilot CLI and handles
token validation/exchange for the Copilot API.

Token type support (per GitHub docs):
  gho_          OAuth token           ✓  (default via copilot login)
  github_pat_   Fine-grained PAT      ✓  (needs Copilot Requests permission)
  ghu_          GitHub App token      ✓  (via environment variable)
  ghp_          Classic PAT           ✗  NOT SUPPORTED

Credential search order (matching Copilot CLI behaviour):
  1. COPILOT_GITHUB_TOKEN env var
  2. GH_TOKEN env var
  3. GITHUB_TOKEN env var
  4. gh auth token  CLI fallback
)annotationsN)Path)OptionalOv23li8tweQw6odWQebzz$https://github.com/login/device/codez+https://github.com/login/oauth/access_tokenz0https://api.github.com/copilot_internal/v2/tokenzhttps://api.githubcopilot.comghp_c                    V ^8  d   QhRRRR/# )   tokenstrreturnbool )formats   "4/home/ubuntu/hermes-agent/hermes_cli/copilot_auth.py__annotate__r   5   s     9 9# 9$ 9    c                H    V P                  4       P                  \        4      # )zICheck if a token is a classic PAT (ghp_*), which Copilot doesn't support.strip
startswith_CLASSIC_PAT_PREFIXr	   s   &r   is_classic_patr   5   s    ;;=##$788r   c                    V ^8  d   QhRRRR/# )r   r	   r
   r   ztuple[bool, str]r   )r   s   "r   r   r   :   s      # *: r   c                t    V P                  4       p V '       g   R# V P                  \        4      '       d   R# R# )zQValidate that a token is usable with the Copilot API.

Returns (valid, message).
)FzEmpty token)Fu3  Classic Personal Access Tokens (ghp_*) are not supported by the Copilot API. Use one of:
  → `copilot login` or `hermes model` to authenticate via OAuth
  → A fine-grained PAT (github_pat_*) with Copilot Requests permission
  → `gh auth login` with the default device code flow (produces gho_* tokens))TOKr   r   s   &r   validate_copilot_tokenr   :   s<    
 KKME##+,,
 	
 r   c                   V ^8  d   QhRR/# )r   r   ztuple[str, str]r   )r   s   "r   r   r   O   s       r   c                 P   \          Fb  p \        P                  ! V R4      P                  4       pV'       g   K2  \	        V4      w  r#V'       g   \
        P                  RW4       K_  W3u # 	  \        4       pV'       d(   \	        V4      w  r#V'       g   \        RV 24      hVR3# R# )zResolve a GitHub token suitable for Copilot API use.

Returns (token, source) where source describes where the token came from.
Raises ValueError if only a classic PAT is available.
 z"Token from %s is not supported: %sz5Token from `gh auth token` is a classic PAT (ghp_*). zgh auth token)r   r   )	COPILOT_ENV_VARSosgetenvr   r   loggerwarning_try_gh_cli_token
ValueError)env_varvalvalidmsgr	   s        r   resolve_copilot_tokenr+   O   s     $ii$**,3/4JE8' < $ E+E2
GuM  o%%Mr   c                   V ^8  d   QhRR/# )r   r   z	list[str]r   )r   s   "r   r   r   n   s      I r   c                    . p \         P                  ! R4      pV'       d   V P                  V4       RR\        \        P
                  ! 4       R,          R,          R,          4      3 Fp  pW 9   d   K  \        P                  P                  V4      '       g   K2  \        P                  ! V\        P                  4      '       g   K_  V P                  V4       Kr  	  V # )zIReturn candidate ``gh`` binary paths, including common Homebrew installs.ghz/opt/homebrew/bin/ghz/usr/local/bin/ghz.localbin)shutilwhichappendr
   r   homer!   pathisfileaccessX_OK)
candidatesresolved	candidates      r   _gh_cli_candidatesr;   n   s    J||D!H(# 	DIIK("U*T12	
 "77>>)$$9bgg)F)Fi( r   c                   V ^8  d   QhRR/# )r   r   Optional[str]r   )r   s   "r   r   r      s      = r   c                    \        4        Fp  p  \        P                  ! V RR.RR^R7      pTP                  ^ 8X  g   K4  TP                  P                  4       '       g   KV  TP                  P                  4       u # 	  R#   \        \        P                  3 d"   p\
        P                  RY4        Rp?K  Rp?ii ; i)zGReturn a token from ``gh auth token`` when the GitHub CLI is available.authr	   T)capture_outputtexttimeoutz#gh CLI token lookup failed (%s): %sN)
r;   
subprocessrunFileNotFoundErrorTimeoutExpiredr#   debug
returncodestdoutr   )gh_pathresultexcs      r   r%   r%      s    %'		^^&'*#	F !fmm&9&9&;&;==&&(( (  ":#<#<= 	LL>M	s   BB=B88B=hostz
github.comtimeout_secondsi,  c               $    V ^8  d   QhRRRRRR/# )r   rM   r
   rN   floatr   r=   r   )r   s   "r   r   r      s-     x x
x x 	xr   c           
        ^ RI p^ RIpV P                  R4      pRV R2pRV R2pVP                  P	                  R\
        RR/4      P                  4       pVP                  P                  VVR	R
RRRR/R7      p VP                  P                  V^R7      ;_uu_ 4       p\        P                  ! VP                  4       P                  4       4      p	RRR4       X	P%                  RR4      pT	P%                  RR4      pT	P%                  RR4      p\'        T	P%                  R\(        4      ^4      pT'       d	   T'       g   \#        R4       R# \#        4        \#        RT 24       \#        RT 24       \#        4        \#        RRRR7       \*        P*                  ! 4       T,           p\*        P*                  ! 4       T8  Ed   \*        P,                  ! T\.        ,           4       TP                  P	                  R\
        RTRR /4      P                  4       pTP                  P                  TTR	R
RRRR/R7      p TP                  P                  T^
R7      ;_uu_ 4       p\        P                  ! TP                  4       P                  4       4      pRRR4       XP%                  R"4      '       d   \#        R#4       TR",          # TP%                  R$R4      pTR%8X  d   \#        R!RRR7       EKI  TR&8X  d[   TP%                  R4      p\1        T\2        \4        34      '       d   T^ 8  d   \3        T4      pM	T^,          p\#        R!RRR7       EK  TR'8X  d   \#        4        \#        R(4       R# TR)8X  d   \#        4        \#        R*4       R# T'       g   EK  \#        4        \#        R+T 24       R# \#        4        \#        R,4       R#   + '       g   i     EL ; i  \         d0   p
\        P!                  RT
4       \#        RT
 24        Rp
?
R# Rp
?
ii ; i  + '       g   i     EL; i  \         d    \#        R!RRR7        EK  i ; i)-zRun the GitHub OAuth device code flow for Copilot.

Prints instructions for the user, polls for completion, and returns
the OAuth access token on success, or None on failure/cancellation.

This replicates the flow used by opencode and the Copilot CLI.
N/zhttps://z/login/device/codez/login/oauth/access_token	client_idscopez	read:userAcceptzapplication/jsonzContent-Typez!application/x-www-form-urlencoded
User-AgentHermesAgent/1.0)dataheaders)rB   z+Failed to initiate device authorization: %su,     ✗ Failed to start device authorization: verification_urizhttps://github.com/login/device	user_coder   device_codeintervalu*     ✗ GitHub did not return a device code.z!  Open this URL in your browser: z  Enter this code: z  Waiting for authorization...T)endflush
grant_typez,urn:ietf:params:oauth:grant-type:device_code.access_tokenu    ✓errorauthorization_pending	slow_downexpired_tokenu,     ✗ Device code expired. Please try again.access_deniedu     ✗ Authorization was denied.u     ✗ Authorization failed: u*     ✗ Timed out waiting for authorization.)urllib.requesturllib.parserstripparse	urlencodeCOPILOT_OAUTH_CLIENT_IDencoderequestRequesturlopenjsonloadsreaddecode	Exceptionr#   rc   printgetmax_DEVICE_CODE_POLL_INTERVALtimesleep_DEVICE_CODE_POLL_SAFETY_MARGIN
isinstanceintrP   )rM   rN   urllibdomaindevice_code_urlaccess_token_urlrX   reqrespdevice_datarL   rZ   r[   r\   r]   deadline	poll_datapoll_reqrK   rc   server_intervals   $$                   r   copilot_device_code_loginr      s    [[F (:;O!&)BC <<!!,#  vx 	
 ..
 
 (?+
 ! C^^##C#44**TYY[%7%7%9:K 5 #'9;\]R0I//-4K;??:/IJANHi:; 
G	-.>-?
@A		{
+,	G	
*$? yy{_,H
))+
 

8==>LL**0;H,
  68	 	 >>)), C/ * 
	''"'==DIIK$6$6$89 > ::n%%&M.))

7B'++#2T*k!$jj4O/C<88_q=P/A#2T*o%G@Ao%G34UG089	G	
67i 544 BCH<SEBCX >== 	#2T*	sf   <%O !3OO =%P0 "3PP0 O	O O P*$PPP-	'P0 -P0 0QQis_agent_turnT	is_visionFc               $    V ^8  d   QhRRRRRR/# )r   r   r   r   r   zdict[str, str]r   )r   s   "r   r   r     s(        	r   c                H    RRRRRRRV '       d   RMR	/pV'       d   R
VR&   V# )zvBuild the standard headers for Copilot API requests.

Replicates the header set used by opencode and the Copilot CLI.
zEditor-Versionzvscode/1.104.1rV   rW   zOpenai-Intentzconversation-editszx-initiatoragentusertruezCopilot-Vision-Requestr   )r   r   rY   s   $$ r   copilot_request_headersr     s;     	*'--wV	G ,2()Nr   )gho_github_pat_ghu_)COPILOT_GITHUB_TOKENGH_TOKENGITHUB_TOKEN)!__doc__
__future__r   rr   loggingr!   r0   rC   r{   pathlibr   typingr   	getLogger__name__r#   rm   COPILOT_DEVICE_CODE_URLCOPILOT_ACCESS_TOKEN_URLCOPILOT_TOKEN_EXCHANGE_URLCOPILOT_API_BASE_URLr   _SUPPORTED_PREFIXESr    rz   r}   r   r   r+   r;   r%   r   r   r   r   r   <module>r      s   $ #   	     			8	$ 1 @ H  P 6   5  H   "# 9
*>*(xx !xz  r   