
    [j                        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dS )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                  T   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!<   d5d%Zd6d7d(Zd8d+Zd9d:d.Zd;d/Zd<d0Zd=d2Zd;d3Zed>d4            Z dS )?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_lockurlreturnNonec                p  K   t          t          |          j                                      dd g          d         }|st	          d          | j        5  | j        dv rt          d          || _        || _	        d| _        | j
                                         d d d            d S # 1 swxY w Y   d S )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)selfr'   r+   s      ;/home/ice/.hermes/hermes-agent/tools/mcp_dashboard_oauth.pypublish_authorization_urlz,DashboardOAuthFlow.publish_authorization_url*   s      #,--11'D6BB1E 	NLMMMZ 	, 	,{333"#=>>>"'D%(D"2DK%))+++	, 	, 	, 	, 	, 	, 	, 	, 	, 	, 	, 	, 	, 	, 	, 	, 	, 	,s   AB++B/2B/      >@timeoutc                   K   t          j        | j        j        |           d {V }|st	          d          | j        st          | j        pd          | j        S )Nz+Timed out waiting for MCP authorization URLz)MCP OAuth flow ended before authorization)asyncio	to_threadr#   waitTimeoutErrorr   r2   r   r4   r8   readys      r5   wait_for_authorization_urlz-DashboardOAuthFlow.wait_for_authorization_url6   ss      '(A(FPPPPPPPP 	NLMMM% 	ZtzX-XYYY%%    coder+   c               f   | j         5  | j                                        rt          d          | j        |t          j        | j        |          st          d          |r|| _        n|r
||f| _        nd| _        | j        	                                 d d d            d S # 1 swxY w Y   d S )NzOAuth callback already receivedzOAuth callback state mismatchz,OAuth callback did not include code or error)
r&   r$   is_setr1   r   secretscompare_digestr"   r!   r3   )r4   rB   r+   r   s       r5   deliver_callbackz#DashboardOAuthFlow.deliver_callback>   s    Z 	' 	'#**,, D !BCCC#+=-d.A5II ! !!@AAA V',$$ V"&'U$ $$&&&	' 	' 	' 	' 	' 	' 	' 	' 	' 	' 	' 	' 	' 	' 	' 	' 	' 	's   BB&&B*-B*     r@tuple[str, str | None]c                   K   t          j        | j        j        |           d {V }|st	          d          | j        rt          d| j                   | j        t          d          | j        S )Nz(Timed out waiting for MCP OAuth callbackzOAuth authorization failed: z4OAuth callback did not include an authorization code)r:   r;   r$   r<   r=   r"   r2   r!   r>   s      r5   wait_for_callbackz$DashboardOAuthFlow.wait_for_callbackV   s      '(<(A7KKKKKKKK 	KIJJJ 	VTd>RTTUUU>!UVVV~rA   c                    | j         5  | j        dk    rt          d          d| _        d | _        d d d            d S # 1 swxY w Y   d S )Nr   r-   r,   )r&   r   r2   r   r4   s    r5   mark_approvedz DashboardOAuthFlow.mark_approved`   s    Z 	 	{g%%"#=>>>$DKDJ		 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	s   )>AAc                    | j         5  | j        dk    r	 d d d            d S d| _        || _        | j                                         | j                                         d d d            d S # 1 swxY w Y   d S )Nr,   r   )r&   r   r   r#   r3   r$   )r4   r   s     r5   
mark_errorzDashboardOAuthFlow.mark_errorg   s    Z 	' 	'{j((	' 	' 	' 	' 	' 	' 	' 	' "DKDJ%))+++ $$&&&	' 	' 	' 	' 	' 	' 	' 	' 	' 	' 	' 	' 	' 	' 	' 	' 	' 	's   A/A A//A36A3dictc                    | j         5  | j        | j        | j        | j        | j        dcd d d            S # 1 swxY w Y   d S )N)r   r   r   r   r   )r&   r   r   r   r   r   rM   s    r5   snapshotzDashboardOAuthFlow.snapshotp   s    Z 	 	<#/+%)%; 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	s   !6::c                8    | j                                          d S N)r%   r3   rM   s    r5   mark_worker_donez#DashboardOAuthFlow.mark_worker_donez   s    rA   c                4    | j                                         S rU   )r%   rD   rM   s    r5   worker_donezDashboardOAuthFlow.worker_done}   s     '')))rA   )r'   r   r(   r)   )r7   )r8   r   r(   r   )rB   r   r+   r   r   r   r(   r)   )rH   )r8   r   r(   rI   )r(   r)   )r   r   r(   r)   )r(   rQ   )r(   r   )!__name__
__module____qualname____annotations__r   r   timer   r   r   r   listr   r   r!   r"   	threadingEventr#   r$   r%   Lockr&   r6   r@   rG   rK   rN   rP   rS   rV   propertyrX    rA   r5   r   r      s        LLL N    di888J8888F$(((((Ed333E3333!&t%!@!@!@N@@@@/4uTTY/Z/Z/ZIZZZZ"'%5u"M"M"MOMMMM,1E)/X]di,j,j,jjjjj',uY_SX_d'e'e'eOeeee$)E)/PU\a$b$b$bLbbbb!E).uSXYYYEYYYY
, 
, 
, 
,& & & & &' ' ' '0       ' ' ' '           * * * X* * *rA   r   mcp_dashboard_oauth_flow)r   z1contextvars.ContextVar[DashboardOAuthFlow | None]_current_dashboard_flowflowr(   Iterator[None]c              #     K   t                               |           }	 d V  t                               |           d S # t                               |           w xY wrU   )re   r3   reset)rf   tokens     r5   dashboard_oauth_flowrk      s\      #''--E-%%e,,,,,%%e,,,,s	   > ADashboardOAuthFlow | Nonec                 4    t                                           S rU   )re   r0   rc   rA   r5   get_dashboard_oauth_flowrn      s    "&&(((rA   )rf   r   r(   rg   )r(   rl   )__doc__
__future__r   r:   contextvarsrE   r_   r]   
contextlibr   dataclassesr   r   typingr   urllib.parser   r	   r   
ContextVarre   r\   rk   rn   rc   rA   r5   <module>rw      s[     # " " " " "            % % % % % % ( ( ( ( ( ( ( (       + + + + + + + + i* i* i* i* i* i* i* i*Z K5tDDD     
 - - - -) ) ) ) ) )rA   