
    `gj                        U d Z ddlmZ ddlZddlZddlZddlZddlZddlm	Z	 ddl
mZmZ ddlmZ ddlmZmZ e G d d	             Z ej&                  d
d      Zded<   e	dd       ZddZy)a  Dashboard-mediated callback bridge for MCP OAuth.

The MCP SDK remains responsible for discovery, DCR, PKCE, state validation and
token exchange. This module only moves the two human/browser callbacks from a
loopback listener into the already-authenticated dashboard session.
    )annotationsN)contextmanager)	dataclassfield)Iterator)parse_qsurlparsec                  X   e Zd ZU ded<   ded<   ded<   ded<   ded<   dZd	ed
<    eej                        Zded<   dZded<   dZ	ded<   dZ
ded<    ee      Zded<    edd      Zded<    eddd      Zded<    eddd      Zded<    eej"                  dd      Zded<    eej"                  dd      Zded<    eej"                  dd      Zded<    eej*                  dd      Zd ed!<   d+d"Zd,d-d#Z	 	 	 	 	 	 	 	 d.d$Zd/d0d%Zd1d&Zd2d'Zd3d(Zd1d)Zed4d*       Z y)5DashboardOAuthFlowstrflow_idserver_name
str | Noneprofilehermes_homeredirect_uriFboolreconnect_live)default_factoryfloat
created_atstartingstatusNauthorization_urlerrorz
list[dict]tools)defaultinitexpected_state)r   r   reprztuple[str, str | None] | None	_callback_callback_error)r   r   r    zthreading.Event_authorization_ready_callback_ready_worker_donezthreading.Lock_lockc                \  K   t        t        |      j                        j                  dd g      d   }|st	        d      | j
                  5  | j                  dv rt        d      || _        || _	        d| _        | j                  j                          d d d        y # 1 sw Y   y xY ww)Nstater   z-OAuth authorization URL did not include state>   r   approvedOAuth flow already endedauthorization_required)r   r	   queryget
ValueErrorr&   r   RuntimeErrorr   r   r#   set)selfurlr(   s      L/root/.hermes/venv/lib/python3.12/site-packages/tools/mcp_dashboard_oauth.pypublish_authorization_urlz,DashboardOAuthFlow.publish_authorization_url*   s     #,,-11'D6B1ELMMZZ 	,{{33"#=>>"'D%(D"2DK%%))+	, 	, 	,s   AB,A	B 	B, B)%B,c                   K   t        j                  | j                  j                  |       d {   }|st	        d      | j
                  st        | j                  xs d      | j
                  S 7 Bw)Nz+Timed out waiting for MCP authorization URLz)MCP OAuth flow ended before authorization)asyncio	to_threadr#   waitTimeoutErrorr   r/   r   r1   timeoutreadys      r3   wait_for_authorization_urlz-DashboardOAuthFlow.wait_for_authorization_url6   sf     ''(A(A(F(FPPLMM%%tzzX-XYY%%% Qs   .A5A3AA5c               p   | j                   5  | j                  j                         rt        d      | j                  "| t        j                  | j                  |      st        d      |r|| _        n|r
||f| _        nd| _        | j                  j                          d d d        y # 1 sw Y   y xY w)NzOAuth callback already receivedzOAuth callback state mismatchz,OAuth callback did not include code or error)
r&   r$   is_setr.   r   secretscompare_digestr"   r!   r0   )r1   coder(   r   s       r3   deliver_callbackz#DashboardOAuthFlow.deliver_callback>   s     ZZ 	'##**, !BCC##+=--d.A.A5I !@AA',$"&'U$  $$&	' 	' 	's   BB,,B5c                  K   t        j                  | j                  j                  |       d {   }|st	        d      | j
                  rt        d| j
                         | j                  t        d      | j                  S 7 Xw)Nz(Timed out waiting for MCP OAuth callbackzOAuth authorization failed: z4OAuth callback did not include an authorization code)r6   r7   r$   r8   r9   r"   r/   r!   r:   s      r3   wait_for_callbackz$DashboardOAuthFlow.wait_for_callbackV   s     ''(<(<(A(A7KKIJJ!=d>R>R=STUU>>!UVV~~ Ls   .BB	ABc                    | j                   5  | j                  dk(  rt        d      d| _        d | _        d d d        y # 1 sw Y   y xY w)Nr   r*   r)   )r&   r   r/   r   r1   s    r3   mark_approvedz DashboardOAuthFlow.mark_approved`   sD    ZZ 	{{g%"#=>>$DKDJ		 	 	s	   )?Ac                    | j                   5  | j                  dk(  r
	 d d d        y d| _        || _        | j                  j	                          | j
                  j	                          d d d        y # 1 sw Y   y xY w)Nr)   r   )r&   r   r   r#   r0   r$   )r1   r   s     r3   
mark_errorzDashboardOAuthFlow.mark_errorg   sk    ZZ 	'{{j(	' 	' "DKDJ%%))+  $$&	' 	' 	's   A2AA22A;c                    | j                   5  | j                  | j                  | j                  | j                  | j
                  dcd d d        S # 1 sw Y   y xY w)N)r   r   r   r   r   )r&   r   r   r   r   r   rG   s    r3   snapshotzDashboardOAuthFlow.snapshotp   sJ    ZZ 	<<#//++%)%;%;	 	 	s   :AAc                8    | j                   j                          y N)r%   r0   rG   s    r3   mark_worker_donez#DashboardOAuthFlow.mark_worker_donez   s        c                6    | j                   j                         S rN   )r%   r?   rG   s    r3   worker_donezDashboardOAuthFlow.worker_done}   s      ''))rP   )r2   r   returnNone)g      >@)r;   r   rS   r   )rB   r   r(   r   r   r   rS   rT   )g     r@)r;   r   rS   ztuple[str, str | None])rS   rT   )r   r   rS   rT   )rS   dict)rS   r   )!__name__
__module____qualname____annotations__r   r   timer   r   r   r   listr   r   r!   r"   	threadingEventr#   r$   r%   Lockr&   r4   r=   rC   rE   rH   rJ   rL   rO   propertyrR    rP   r3   r   r      sk   L ND dii8J8FC$(z(E:d3E:3!&t%!@NJ@/4TTY/ZI,Z"'5u"MOZM,1)//X]di,j/j',Y__SX_d'eO_e$))//PU\a$bL/b!)..uSXYE>Y
,&' ' 	'
 ' 
'0'  * *rP   r   mcp_dashboard_oauth_flow)r   z1contextvars.ContextVar[DashboardOAuthFlow | None]_current_dashboard_flowc              #     K   t         j                  |       }	 d  t         j                  |       y # t         j                  |       w xY wwrN   )rb   r0   reset)flowtokens     r3   dashboard_oauth_flowrg      s;     #''-E-%%e,%%e,s   A3 AA

Ac                 *    t         j                         S rN   )rb   r-   r`   rP   r3   get_dashboard_oauth_flowri      s    "&&((rP   )re   r   rS   zIterator[None])rS   zDashboardOAuthFlow | None)__doc__
__future__r   r6   contextvarsr@   r\   rZ   
contextlibr   dataclassesr   r   typingr   urllib.parser   r	   r   
ContextVarrb   rY   rg   ri   r`   rP   r3   <module>rr      s    #      % (  + i* i* i*Z K5tD J 
 - -)rP   