
    	D,j>                         d dl Z d dlZd dlZd dl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mZ d dlZd dlmZ d dlmZ d Zd Zd Zd ZddZd Zd Zd Z G d d          Zd Zedk    r e             dS dS )    N)parse_qsurlparse)urls)InputOutputc                    	 t          j        ddd|  id          }|                                 |                                }|                    di                               dd          S # t          $ r Y dS w xY w)	a
  
    Checks if the user is on a free tier for OpenRouter.

    Args:
        api_key: The OpenRouter API key to check.

    Returns:
        A boolean indicating if the user is on a free tier (True) or paid tier (False).
        Returns True if the check fails.
    z%https://openrouter.ai/api/v1/auth/keyAuthorizationzBearer    )headerstimeoutdatais_free_tierT)requestsgetraise_for_statusjson	Exception)api_keyresponser   s      _/home/rurouni/.local/share/uv/tools/aider-chat/lib/python3.11/site-packages/aider/onboarding.pycheck_openrouter_tierr      s    <3$&9&9&9:
 
 

 	!!###}}xx##''===   tts   A-A0 0
A>=A>c                      t           j                            d          } | rt          |           }|rdS dS g d}|D ]*\  }}t           j                            |          }|r|c S +dS )z
    Attempts to select a default model based on available API keys.
    Checks OpenRouter tier status to select appropriate model.

    Returns:
        The name of the selected model, or None if no suitable default is found.
    OPENROUTER_API_KEYz$openrouter/deepseek/deepseek-r1:freez$openrouter/anthropic/claude-sonnet-4))ANTHROPIC_API_KEYsonnet)DEEPSEEK_API_KEYdeepseek)OPENAI_API_KEYzgpt-4o)GEMINI_API_KEYzgemini/gemini-2.5-pro-exp-03-25)VERTEXAI_PROJECTz"vertex_ai/gemini-2.5-pro-exp-03-25N)osenvironr   r   )openrouter_keyr   model_key_pairsenv_key
model_nameapi_key_values         r   try_to_select_default_modelr'   ,   s     Z^^$899N :,^<< 	:9999  O  /  
w// 		 4    c                 P   |                      d           |                     dd          ry|                    dd           t          | |          }|r&|t          j        d<   |                    d	           d
S |                    d           |                     d           dS )a  
    Offers OpenRouter OAuth flow to the user if no API keys are found.

    Args:
        io: The InputOutput object for user interaction.
        analytics: The Analytics object for tracking events.

    Returns:
        True if authentication was successful, False otherwise.
    z6OpenRouter provides free and paid access to many LLMs.z-Login to OpenRouter or create a free account?y)defaultoauth_flow_initiated
openrouterproviderr   oauth_flow_successToauth_flow_failurez8OpenRouter authentication did not complete successfully.F)tool_outputconfirm_askeventstart_openrouter_oauth_flowr    r!   
tool_error)io	analyticsr"   s      r   offer_openrouter_oauthr9   O   s     NNKLLL	~~7    R 	.FFF4RCC 	 0>BJ+,OO01114 	,---
PQQQ 5r(   c                 X   | j         r| j         S t                      }|r2|                    d| d           |                    d|           |S d}|                    |           t	          ||           t                      }|r|S |                    t          j        d           dS )a  
    Selects a default model based on available API keys if no model is specified.
    Offers OAuth flow for OpenRouter if no keys are found.

    Args:
        args: The command line arguments object.
        io: The InputOutput object for user interaction.
        analytics: The Analytics object for tracking events.

    Returns:
        The name of the selected model, or None if no suitable default is found.
    zUsing z% model with API key from environment.auto_model_selection)modelz9No LLM model was specified and no API keys were provided.z%Open documentation URL for more info?N)r<   r'   tool_warningr4   r9   	offer_urlr   models_and_keys)argsr7   r8   r<   no_model_msgs        r   select_default_modelrB   t   s     z z'))E 
MMMMNNN.e<<<NLOOL!!! 2y))) ())E LL%'NOOOOOr(   $!  !  c                     t          | |dz             D ]F}	 t          j        d|fd           5  |cd d d            c S # 1 swxY w Y   7# t          $ r Y Cw xY wd S )N   	localhost)rangesocketserver	TCPServerOSError)
start_portend_portports      r   find_available_portrO      s    j(Q,//  	'd(;TBB                     	 	 	H	 4s1   A?AA	AA	A
AAc                  @   t          j        d          } t          j                    }|                    |                     d                     t          j        |                                          	                    d          
                    d          }| |fS )N@   utf-8   =)secretstoken_urlsafehashlibsha256updateencodebase64urlsafe_b64encodedigestrstripdecode)code_verifierhashercode_challenges      r   generate_pkce_codesrb      s    )"--M^F
MM-&&w//000-fmmoo>>EEdKKRRSZ[[N.((r(   c                 &   	 t          j        dddi| |ddd          }|                                 |                                }|                    d          }|s4|                    d	           |                    d
|j                    d S |S # t           j        j        $ r |                    d           Y d S t           j        j	        $ r\}|                    d|j
        j         d|j
        j                    |                    d
|j
        j                    Y d }~d S d }~wt           j        j        $ r#}|                    d|            Y d }~d S d }~wt          $ r#}|                    d|            Y d }~d S d }~ww xY w)Nz&https://openrouter.ai/api/v1/auth/keyszContent-Typezapplication/jsonS256)coder_   code_challenge_method   )r
   r   r   keyz.Error: 'key' not found in OpenRouter response.z
Response: z<Error: Request to OpenRouter timed out during code exchange.z*Error exchanging code for OpenRouter key:  z'Unexpected error during code exchange: )r   postr   r   r   r6   text
exceptionsTimeout	HTTPErrorr   status_codereasonRequestExceptionr   )re   r_   r7   r   r   r   es          r   exchange_code_for_keyrs      s   "=4#%78!.)/ 
 	
 	
 	
 	!!###}}((5// 	MMJKKKMM6x}667774&   
TUUUtt(   
=
&= =)*):= =	
 	
 	
 	41:?44555ttttt/   
F1FFGGGttttt   
CCCDDDttttts=   BB B )FFAD++FE  F-FFc                 	    t                      s,                     d                                d           dS d dddt          j                    t          j                     G fddt          j        j                   fd}t          j        |d	
          }|                                 	                    d          sA                     d           
                                 |                    d           dS rA                                
                                 |                    d           dS t                      \  }}d}|dd}| dd                    d |                                D                        }                     d                                             t          |           d}	                     d|	 d                                d           	 t!          j        |           n# t$          $ r Y nw xY wd}
	 	                    |	dz             nS# t&          $ rF                      d           |                    ddd           d	}

                                 Y nw xY w|                    d           |
rdS r2                     d             |                    dd           dS s.                     d!           |                    dd"           dS                      d#           |                    d$d"           t-          |           }|rU|t.          j        d%<   	 t.          j                            d&          }t/          j        |d	'           t.          j                            |d(          }t#          |d)d*+          5 }|                    d,| d-           ddd           n# 1 swxY w Y                        d.                                             |                    d/d"           |S # t$          $ r^}                     d0|                                 d1           |                    d2dt;          |                     |cY d}~S d}~ww xY w                     d!           |                    ddd3           dS )4z>Initiates the OpenRouter OAuth PKCE flow using a local server.z7Could not find an available port between 8484 and 8584.zBPlease ensure a port in this range is free, or configure manually.Nzhttp://localhost:/callback/aiderc                   $    e Zd Z fdZd ZdS )9start_openrouter_oauth_flow.<locals>.OAuthCallbackHandlerc                    t          | j                  }|j        dk    rt          |j                  }d|v r}|d         d         |                     d           |                     dd           |                                  | j                            d           	                                 d S |                     d           |                     d	t          j                   |                                  d S |                     d           |                     d	t          j                   |                                  | j                            d
           d S )Nru   re   r      zContent-typez	text/htmls}   <html><body><h1>Success!</h1><p>Aider has received the authentication code. You can close this browser tab.</p></body></html>i.  Locations	   Not Found)r   pathr   querysend_responsesend_headerend_headerswfilewritesetr   website)selfparsed_pathquery_params	auth_codeserver_errorshutdown_servers      r   do_GETz@start_openrouter_oauth_flow.<locals>.OAuthCallbackHandler.do_GET   sc   "49--K#444'(9::\)) ,V 4Q 7I&&s+++$$^[AAA$$&&&J$$M   $''))))) &&s+++$$Z>>>$$&&&&&
 ""3'''  T\:::  """
  .....r(   c                     d S N )r   formatr@   s      r   log_messagezEstart_openrouter_oauth_flow.<locals>.OAuthCallbackHandler.log_message  s    Dr(   N)__name__
__module____qualname__r   r   )r   r   r   s   r   OAuthCallbackHandlerrw      sH        	/ 	/ 	/ 	/ 	/ 	/ 	/@	 	 	 	 	r(   r   c                     	 t          j        df          5 }                     d d                                                                            s<|                                  t          j        d                                           <                    dd           d d d            d S # 1 swxY w Y   d S # t          $ r8}d|                                                                   Y d }~d S d }~ww xY w)NrG   zTemporary server listening on T)log_onlyg?zShutting down temporary server.z)Failed to start or run temporary server: )	rI   rJ   r2   r   is_sethandle_requesttimesleepr   )	httpdrr   r   callback_urlr7   rN   r   server_startedr   s	     r   
run_serverz/start_openrouter_oauth_flow.<locals>.run_server
  s   	"'d(;=QRR 	QV[NNNY]^^^""$$$)0022 $((*** JsOOO	 *0022 $
 @4PPP	Q 	Q 	Q 	Q 	Q 	Q 	Q 	Q 	Q 	Q 	Q 	Q 	Q 	Q 	Q 	Q 	Q 	Q  	" 	" 	"JqJJL   !!!!!!!!!	"s;   C
 BB=0C
 =CC
 CC
 

D-DDT)targetdaemonr	   )r   z8Temporary authentication server failed to start in time.rF   zhttps://openrouter.ai/authrd   )r   ra   rf   ?&c              3   *   K   | ]\  }}| d | V  dS )=Nr   ).0kvs      r   	<genexpr>z.start_openrouter_oauth_flow.<locals>.<genexpr>5  s0      *V*V$!Qa::!::*V*V*V*V*V*Vr(   zG
Please open this URL in your browser to connect Aider with OpenRouter:z
Waiting up to z, minutes for you to finish in the browser...zUse Control-C to interrupt.F<   z
OAuth flow interrupted.oauth_flow_failedr-   user_interrupt)r/   rp   zAuthentication failed: z&Authentication with OpenRouter failed.r.   zCompleting authentication...oauth_flow_code_receivedr   z~/.aider)exist_okzoauth-keys.envarR   )encodingzOPENROUTER_API_KEY="z"
zDAider will load the OpenRouter key automatically in future sessions.r0   z:Successfully obtained key, but failed to save it to file: zBSet OPENROUTER_API_KEY environment variable for this session only.oauth_flow_save_failedcode_exchange_failed)rO   r6   	threadingEventhttpserverSimpleHTTPRequestHandlerThreadstartwaitr   joinrb   itemsr2   print
webbrowseropenr   KeyboardInterruptr=   r4   rs   r    r!   r{   
expandusermakedirsr   str)r7   r8   r   server_threadr_   ra   auth_url_baseauth_paramsauth_urlMINUTESinterruptedr   
config_dirkey_filefrr   r   r   r   rN   r   r   r   s   `               @@@@@@@r   r5   r5      s
      D 
OPPP
Z[[[t<t<<<LIL_&&No''O# # # # # # # # #t{C # # #J" " " " " " " " " " "$ $JtDDDM q)) 
PQQQ1%%%t  
l###1%%%t %8$9$9!M>0M$(!' K
  XX#((*V*V+BSBSBUBU*V*V*V"V"VXXHNN]^^^NN	(OOOGNN[g[[[\\\NN0111!!!!    KWr\2222   
3444+lK[\\\ q!!! t 
>>>???+l<XXXt 
>???+lCCCtNN1222OO.OFFF $I}bAAG +2
'(	++J77JK
T2222w||J0@AAHhg666 =!;w;;;<<<= = = = = = = = = = = = = = = OObcccNNOO0<OHHHN 	 	 	MMZWXZZ[[[OO`aaaOO4|TWXYTZTZO[[[NNNNNN	 	>???+lKabbbtsj   H2 2
H?>H?I AJ/.J/ A'Q 'PQ PQ PAQ 
S$AR=7S=Sc                       e Zd Zd ZdS )DummyAnalyticsc                     d S r   r   )r   r@   kwargss      r   r4   zDummyAnalytics.event  s    r(   N)r   r   r   r4   r   r(   r   r   r     s#            r(   r   c                  Z   t          d           t          dddddd          } t                      }dt          j        v rt          d	           t          | |          }|r+t          d
           t          d|dd          d           nt          d           t          d           dS )z0Main function to test the OpenRouter OAuth flow.z&Starting OpenRouter OAuth flow test...TFNBLUERED)prettyyesinput_history_filechat_history_filetool_output_colortool_error_colorr   z:Warning: OPENROUTER_API_KEY is already set in environment.z#
OAuth flow completed successfully!z"Obtained API Key (first 5 chars): r	   z...z$
OAuth flow failed or was cancelled.z%
OpenRouter OAuth flow test finished.)r   r   r   r    r!   r5   )r7   r8   r   s      r   mainr     s    	
2333 
 
 
 
B   I rz))JKKK *"i88G 74555C72A2;CCCDDDD 	5666	
233333r(   __main__)rC   rD   )rZ   rV   http.serverr   r    rT   rI   r   r   r   urllib.parser   r   r   aiderr   aider.ior   r   r'   r9   rB   rO   rb   rs   r5   r   r   r   r   r(   r   <module>r      s         				               + + + + + + + +                     4     F" " "J!P !P !PJ	 	 	 	) ) )# # #Ni i iZ       4 4 4D zDFFFFF r(   