
    AHjja                     r   U d 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	 ddl
mZmZmZmZ 	 ddlZddlZdZeed<   ddlmZ d	d
ddddddgdddddddg ddddddddddgddd d!d"d#dg dd$d%d&
d'd(d)d*d+dd,gd-d.gd/d0gd1	d2d3d4dddd5d6gd7d8gZee   ed9<    ej0                  d:      Zd;Zd<Zd=Zd>Zd?Zd@ZdAZ dBZ!dCZ"dDZ#dEZ$dFZ%dGefdHZ&dIe'dJe'dGe'fdKZ(dLe'dGe'fdMZ)dLe'dGe'fdNZ*dLe'dGe'fdOZ+dLe'dGe'fdPZ,dLe'dGe'fdQZ-dLe'dGe'fdRZ.dGe'fdSZ/dTe'dGe'fdUZ0dVe'dGe'fdWZ1dXZ2 G dY dZ      Z3d\d[Z4y# e$ r	 dZdZdZY w xY w)]u   
LiteLLM Interactive Setup Wizard

Guides users through selecting LLM providers, entering API keys,
and generating a proxy config file — mirroring the Claude Code onboarding UX.
    N)Path)DictListOptionalSetT_HAS_RAW_TERMINALF)check_valid_keyopenaiOpenAIzGPT-4o, GPT-4o-mini, o3-miniOPENAI_API_KEYzsk-...zgpt-4o-minizgpt-4o)idnamedescriptionenv_keykey_hint
test_modelmodels	anthropic	Anthropicz&Claude Opus 4.6, Sonnet 4.6, Haiku 4.5ANTHROPIC_API_KEYz
sk-ant-...claude-haiku-4-5-20251001)zclaude-opus-4-6zclaude-sonnet-4-6r   geminizGoogle Geminiz Gemini 2.0 Flash, Gemini 2.5 ProGEMINI_API_KEYzAIza...zgemini/gemini-2.0-flashzgemini/gemini-2.5-proazurezAzure OpenAIzGPT-4o via AzureAZURE_AI_API_KEYzyour-azure-keyz$https://<resource>.openai.azure.com/z2024-07-01-preview)
r   r   r   r   r   r   r   needs_api_baseapi_base_hintapi_versionbedrockzAWS BedrockzClaude 3.5, Llama 3 via AWSAWS_ACCESS_KEY_IDzAKIA...z1bedrock/anthropic.claude-3-5-sonnet-20241022-v2:0AWS_SECRET_ACCESS_KEYAWS_REGION_NAMEzyour-secret-keyz	us-east-1)	r   r   r   r   r   r   r   
extra_keysextra_hintsollamaOllamaz&Local models (llama3.2, mistral, etc.)zollama/llama3.2zollama/mistralzhttp://localhost:11434)r   r   r   r   r   r   r   api_base	PROVIDERSz\033\[[^m]*mz[38;2;215;119;87mz[2mz[1mz[38;2;78;186;101mz[38;2;177;185;249mz[38;2;153;153;153mz[0mu   ✔u   ✘z[?25lz[?25hz[{}Areturnc                      t         j                  j                         xr! t        j                  j                  d      d u S )NNO_COLOR)sysstdoutisattyosenvironget     L/root/tools/cai/cai_env/lib/python3.12/site-packages/litellm/setup_wizard.py_supports_colorr5      s,    ::E2::>>*#=#EEr3   codetextc                 2    t               r|  | t         S |S N)r5   _RESET)r6   r7   s     r4   _cr;      s    &5&7dVD6&"ATAr3   tc                 "    t        t        |       S r9   )r;   _ORANGEr<   s    r4   oranger@      s    gq>r3   c                 "    t        t        |       S r9   )r;   _BOLDr?   s    r4   boldrC          eQ<r3   c                 "    t        t        |       S r9   )r;   _GREENr?   s    r4   greenrG      s    fa=r3   c                 "    t        t        |       S r9   )r;   _BLUEr?   s    r4   bluerJ      rD   r3   c                 "    t        t        |       S r9   )r;   _GREYr?   s    r4   greyrM      rD   r3   c                 "    t        t        |       S r9   )r;   _DIMr?   s    r4   dimrP      s    dA;r3   c                      t        d      S )zGReturn a styled divider line (evaluated at call-time, not import-time).u     ╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌)rP   r2   r3   r4   _dividerrR      s     !!r3   promptc                     t         j                  j                         rt        j	                  d |       }nt        j	                  d|       }t        |      j                         S )z
    Like input() but wraps ANSI sequences in readline ignore markers
    (\001...\002) so readline correctly tracks the cursor column.
    In non-TTY contexts, strips ANSI entirely so no escape codes appear.
    c                 *    d| j                          dS )N)group)ms    r4   <lambda>z_styled_input.<locals>.<lambda>   s    T!'')D+A r3    )r,   r-   r.   _ANSI_REsubinputstrip)rS   	rl_prompts     r4   _styled_inputra      sI     zzLL!A6J	LLV,	!!##r3   valuec                     | j                  dd      j                  dd      j                  dd      j                  dd      j                  d	d
      S )zBEscape a string for safe embedding in a double-quoted YAML scalar.\z\\"z\"
z\nz\r	z\t)replace)rb   s    r4   _yaml_escaperj      sG     	dF#	e		u		u		u	r3   u+  
  ██╗     ██╗████████╗███████╗██╗     ██╗     ███╗   ███╗
  ██║     ██║╚══██╔══╝██╔════╝██║     ██║     ████╗ ████║
  ██║     ██║   ██║   █████╗  ██║     ██║     ██╔████╔██║
  ██║     ██║   ██║   ██╔══╝  ██║     ██║     ██║╚██╔╝██║
  ███████╗██║   ██║   ███████╗███████╗███████╗██║ ╚═╝ ██║
  ╚══════╝╚═╝   ╚═╝   ╚══════╝╚══════╝╚══════╝╚═╝     ╚═╝
c            	          e Zd ZdZedd       Zedd       Zedd       Zedee	   fd       Z
edefd       Zed	ed
ee   dedefd       Zedee	   fd       Zedee	   fd       Zedee	   de	eef   fd       Zede	defd       Zede	dedefd       Zedd       Zedee	   de	eef   dedefd       Zededededdfd       Zededededdfd       Zy)SetupWizardu   
    Interactive onboarding wizard: provider selection → API keys → config file.

    All methods are static — the class is purely a namespace with clear
    single-responsibility sections. Entry point: SetupWizard.run().
    r)   Nc                      	 t         j                          y # t        t        f$ r t	        dt        d       d       Y y w xY w)Nz

  zSetup cancelled.rf   )rl   _wizardKeyboardInterruptEOFErrorprintrM   r2   r3   r4   runzSetupWizard.run   s?    	9!!8, 	9F4 234B78	9s    'A Ac                  \   t         j                          t        dt        d              t                t         j	                         } t         j                  |       }t         j                         \  }}t        t        j                               dz  }	 |j                  t         j                  | ||             t         j                  |||       t         j                  |||       y # t        $ r6}t        dt        t        dz          d|        t        d       Y d }~y d }~ww xY w)N  zLets get started.zlitellm_config.yaml
  z Could not write config: z9  Try running from a directory you have write access to.
)rl   _print_welcomerq   rC   _select_providers_collect_keys_proxy_settingsr   r/   getcwd
write_text_build_configOSError_CROSS_print_success_offer_start)	providersenv_varsport
master_keyconfig_pathexcs         r4   rn   zSetupWizard._wizard   s    ""$4+,-./113	,,Y7&668j299;'*??	"")))XzJ 	"";jA  dJ?  	Df'AABC1SEJKNO	s   &C, ,	D+5,D&&D+c                  z   	 t         j                  j                  d      } t	                t	        t        t        j                  d                   t	        dt        d       dt        d       dt        d	| z                 t	                t	        t                      t	                y # t        $ r d} Y w xY w)
Nlitellmunknownrf   rt   Welcomez to LiteLLMrv   v)	importlibmetadataversion	Exceptionrq   r@   LITELLM_ASCIIrstriprC   rM   rR   )r   s    r4   rw   zSetupWizard._print_welcome   s    	 ((00;G 	f]))$/016)$%T$y/):!Dw<O;PQRhj  	 G	 s   B, ,B:9B:c                      t         st        j                         S 	 t        j                         S # t        $ r t        j                         cY S w xY w)zKArrow-key multi-select. Falls back to number input if /dev/tty unavailable.)r   rl   _select_fallback_select_interactiver~   r2   r3   r4   rx   zSetupWizard._select_providers
  sH     !//11	22244 	2//11	2s   0 AAc                  &   t         t        J t        dd      5 } | j                         }t        j                  |      }	 t        j
                  |       | j                  d      }|dk(  r| j                  d      }|dk(  rU| j                  d      }d|j                  dd	
      z   t        j                  |t         j                  |       cddd       S d|j                  dd	
      z   t        j                  |t         j                  |       cddd       S |j                  dd	
      t        j                  |t         j                  |       cddd       S # t        j                  |t         j                  |       w xY w# 1 sw Y   yxY w)z,Read one keypress from /dev/tty in raw mode.Nz/dev/ttyrb         [z[zutf-8ri   )errors)
termiosttyopenfileno	tcgetattrsetrawreaddecode	tcsetattr	TCSADRAIN)tty_fhfdoldchch2ch3s         r4   	_read_keyzSetupWizard._read_key  sV    CO	
3*d# 	>vB##B'C>

2[[^= ++a.Cd{$kk!n&GI)NN !!"g&7&7=	> 	> "CJJwyJ$II !!"g&7&7=	> 	> yyy;!!"g&7&7=	> 	> !!"g&7&7=	> 	>s<   &FA'E)%FE-%FE.%F'FFFcursorselectedfirst_renderc                    dt        d       dt        d      dz   dg}t        t              D ]s  \  }}|| k(  rt	        d      nd}||v rt        d      n
t        d      }|| k(  rt        |d	         n|d	   }|j                  d
| d| d| d
t        |d          d	       u |j                  d       dj                  |      }	|sKt               rAt        j                  j                  t        j                  |	j                  d                   t        j                  j                  |	       t        j                  j                          |	j                  d      S )zFDraw or redraw the provider list. Returns the number of lines printed.ru   Add your first modelrf   u;     ↑↓ to navigate · Space to select · Enter to confirm   ❯rv   u   ◉u   ○r   rt   r   r[   )rC   rM   	enumerater(   rJ   rG   appendjoinr5   r,   r-   write_MOVE_UPformatcountflush)
r   r   r   linesiparrowbulletname_strcontents
             r4   _render_selectorzSetupWizard._render_selector*  s6    4./03NORVV

 i( 	WDAq#$;DKCE%&(]U5\UF*+v+tAfI1V9HLL2eWAfXQxj4-@P;Q:RRTUV		W
 	T''%. 1JJX__W]]4-@AB

!

}}T""r3   c                     d} t               }t               rAt        j                  j	                  t
               t        j                  j                          	 t        j                  | |d       	 t        j                         }d}|dk(  r| dz
  t        t              z  } d}nY|dk(  r| dz   t        t              z  } d}n<|dk(  r|j                  | h       d}n"|d	v r|s|j                  |        n%|d
v rt        |rt        j                  | |d       	 t               rBt        j                  j	                  t               t        j                  j                          	 t!        |      D cg c]  }t        |    c}S # t               rBt        j                  j	                  t               t        j                  j                          w w xY wc c}w )Nr   T)r   Fz[Ar   z[Brv   )rg   rf   ))setr5   r,   r-   r   _CURSOR_HIDEr   rl   r   r   lenr(   symmetric_difference_updateaddro   _CURSOR_SHOWsorted)r   r   keydirtyr   s        r4   r   zSetupWizard._select_interactive@  s    UJJ\*JJ	#(((M!++-(?$qjC	N:F EH_$qjC	N:F ECZ88&B EL(# V,,,++00PU0V'    

  .

  "&,X&67	!77	  

  .

  " ! 8s   C F 3GAGc                     t                t        dt        d              t        t        d             t                t        t        d      D ]F  \  } }t        dt        t        |       dz          dt        |d          dt        |d                 H t                	 t        dt        d	       d
      }|st        t        d             0	 |j                  dd      j                  d      D cg c]+  }|j                         rt        |j                               - }}t        |D ch c]   }d|cxk  rt        t              k  sn n|" c}      }|s&t        t        dt        t               d             |D  cg c]  } t        | dz
      c} S c c}w c c}w c c} w # t        $ r t        t        d             Y nw xY w0)z=Number-based fallback when raw terminal input is unavailable.rt   r   zG  Enter numbers separated by commas (e.g. 1,2). Press Enter to confirm.r   .rv   r   r   r   z Provider(s): z&  Please select at least one provider.,z  Enter numbers between 1 and z-  Enter numbers separated by commas, e.g. 1,3)rq   rC   rM   r   r(   strra   rJ   ri   splitr_   intr   r   
ValueError)r   r   rawxnumsnvalids          r4   r   zSetupWizard._select_fallbacke  s    	4./012Y	

 	i+ 	YDAqBtCFSL)*!D6O+<BtAmDT?U>VWX	Y"T%[M @ACdCDEM ![[c288=wwy 	N 
 4La13KS^3KLM$!?I?OqQRS278Q	!a%(88
  M 9 MdJKLM! sH   #F/ 70F 'F/ 2F%F%.F/ F/ 
F*F/  F/ /GGr   c                    i }t                t        t                      t                t        dt        d              t        t        d             t        t        d             t                | D ]e  }|d   't        dt	        |d          dt        d              0t
        j                  |      }|sHt        |j                  d	g       |j                  d
g             D ]4  \  }}t        dt        d       d| dt        |       d      }|s0|||<   6 |j                  d      rt        dt        d       dt        |j                  dd             d      }|r||d|d   j                          <   t        dt        d       dt        d       d      }|r||d|d   j                          <   t
        j                  ||      ||d   <   h |S )Nrt   zEnter your API keysz4  Keys are stored only in the generated config file.zI  Tip: add litellm_config.yaml to .gitignore to avoid committing secrets.r   r   : z!no key needed (uses local Ollama)r#   r$   r   rv   r   z Azure endpoint URL r   r[   _LITELLM_AZURE_AI_API_BASE_r   z Azure deployment name z(e.g. my-gpt4o)_LITELLM_AZURE_DEPLOYMENT_)rq   rR   rC   rM   rG   rl   _prompt_keyzipr1   ra   rJ   upper_validate_and_report)	r   r   r   r   	extra_key
extra_hintvalr'   
deployments	            r4   ry   zSetupWizard._collect_keys  s   #%hj4-./01dIJK[	

 	 !	NA|#qy)*"T2U-V,WX ))!,C),lB'}b)A* .%	: $beQyk4
CSBTTV$WX*-HY'. uu%&(e%9$quu_VX?Y:Z9[[]^ PXH:1T7==?:KLM*e%<TBS=T<UUWX
  # 4QtW]]_4EF
 &1%E%Ea%MHQy\"C!	NF r3   providerc           	         t        | j                  dd            }	 t        dt        d       dt	        | d          d| d      }|r|S t        t        d	             t        t        d
            j                         dk(  ryi)zIPrompt for a provider's API key, with skip option. Returns the key or ''.r   r[   rt   r   rv   r   	 API key r   z5  Key is required. Leave blank to skip this provider.z  Skip? (y/N): y)rM   r1   ra   rJ   rC   rq   lower)r   hintr   s      r4   r   zSetupWizard._prompt_key  s     HLLR01T%[M4(8#9":)D6LC 
$NOPT"345;;=D r3   api_keyc           
      L   | j                  d      }|s|S 	 t        dt        d| d   z   dz          d       t        ||      }|r-t        dt	        t
               d	t        | d          d
       |S t        dt         d	t        | d          d	t        d              t        dt        d       dt        d       d      j                         dk7  r|S t        | j                  dd            }t        dt        d       d	t        | d          d| d      }|s|S |})z
        Validate credentials using litellm.utils.check_valid_key and print result.
        Offers a re-entry loop on failure. Returns the final (possibly re-entered) key.
        r   Trt   zTesting connection to r   z...)r   )modelr   rv   z connected successfullyu   — invalid API keyr   z Re-enter key? z(y/N)r   r   r   r[   r   )r1   rq   rM   r	   rG   _CHECKrC   r   ra   rJ   r   )r   r   r   r   r   new_keys         r4   r   z SetupWizard._validate_and_report  sH    %-LL$>
NT2Xf5EEMNOP $*gFEvqhv.>)?(@@WX BvhaXf%5 67q>S9T8UVW4;-tG}oRPQWWY Z45D#T%[M4(8#9":)D6LG G3 r3   c                     t                t        t                      t                t        dt        d              t                d} 	 t        dt	        d       dt        d       d      }|snH|j                         r#dt        |      cxk  rd	k  rn nt        |      } nt        t        d
             ot        dt	        d       dt        d       d      }|r|ndt        j                  d       }| |fS )Nrt   zProxy settingsi  r   z Port z[4000]r   r   i  u(     Enter a valid port number (1–65535).z Master key z[auto-generate]zsk-    )
rq   rR   rC   ra   rJ   rM   isdigitr   secretstoken_urlsafe)r   port_rawkey_rawr   s       r4   rz   zSetupWizard._proxy_settings  s    hj4()*+,$r$u+fT(^<LB%OPH!a3x=&AE&A8}$ABC   "T%[MdCT>U=VVX YZ 'Ws73H3H3L2M-N
Zr3   r   r   c                    t        |      }dg}| D ]t  }|d   d u xs |d   |v }|s|d   dk(  r0|j                  d|d   j                          d      }|sHd| g}n|d   }|D ]  }	d	|	v r|	j                  d	      d
   n|	}
|d   dk(  rd|
 n|
}|d| dd|	 gz  }|d   r|d   |v r|j	                  d|d           |j                  d      r+|j	                  dt        t        |d                d       nX|j                  d      rGd|d   j                          }||v r-|j	                  dt        |j                  |             d       |j                  d      s|j	                  d|d            w |dddt        |       ddgz  }|j                         D ci c]  \  }}|j                  d      r|| }}}|r[|j	                  d       |j                         D ]&  \  }}|j	                  d| dt        |       d       ( |j	                  d       dj                  |      S c c}}w )Nzmodel_list:r   r   r   r   r[   zazure/r   /zazure-z  - model_name: z    litellm_params:z      model: z      api_key: os.environ/r'   z      api_base: "re   r   r   r   z      api_version: zgeneral_settings:z  master_key: "	_LITELLM_zenvironment_variables:rt   z: "rf   )dictpopr   r   r   r1   rj   r   items
startswithr   )r   r   r   env_copyr   r   	has_credsr   r   r   raw_displaydisplayazure_base_keykr   	real_varss                   r4   r}   zSetupWizard._build_config  s    > &	KA),H)0HIw'!%\\040ABB
 "":,/08 K69Ulekk#.r245dGw4FF;-0K&wi0)#E7+ 
 Y<AiLH$<LL#=a	l^!LM55$LL+LQz]9K,L+MQO UU+,'B1T7==?BS%TN%1/X\\.=Y0Z/[[\] 55'LL#6q7G6H!IJ-K!&	KP 	l:67q9	
 	
 '/nn&6Xdaall;>WQTX	XLL12!) <1r!CQ'8:;<LLyy Ys   2IIr   r   c           
      $   t                t        t                      t                t        dt        t        dz          dt	        t        |                     t                t        dt	        d              t                t        dt        d       d|  d|        t                t        dt	        d	              t                t        d
|        t        d|        t                t        t                      t                y )Nrt   z Config savedu    → zTo start your proxy:z    $z litellm --config  --port zThen set your client:,    export OPENAI_BASE_URL=http://localhost:    export OPENAI_API_KEY=)rq   rR   rG   r   rC   r   rM   )r   r   r   s      r4   r   zSetupWizard._print_successJ  s    hj5/1235c+>N9O8PQR4./012T#YK1+htfMN4/0123<TFCD*:,78hjr3   c           
         t        dt        d       dt        d       d      j                         }|dvrRt	                t	        dt        d|         d	       t	                t	        t        d
| d             t	                y t	                t	        t                      t	                t	        dt        d       d|        t	                t	        t        d             t	                t	        d|        t	        d|        t	                t	        t        d             t	                t	        d| d       t	                t	        t        d             t	                t	        d| dt        d              t	                t	        t                      t	                t	        dt        t               dt        d              t	                t        j                  d      }t        j                  j                  |xs dd      }	 t        j                  ||dt        |       dt        |             y # t         $ r=}t	        dt        t"        dz          d |        t	        d!|  d"| d#       Y d }~y d }~ww xY w)$Nrt   r   z Start the proxy now? z(Y/n)r   )r[   r   yesz  Run zlitellm --config z whenever you're ready.z2  Quick test once running:  curl http://localhost:z/healthzProxy is starting onz http://localhost:z>  Your proxy is OpenAI-compatible. Point any OpenAI SDK at it:r  r  z#  Quick test (in another terminal):z    curl http://localhost:z  Dashboard:z    http://localhost:z/ui  z(login with your master key)u    Starting…  z(Ctrl+C to stop)scriptsr[   r   z--configz--portru   z Could not start proxy:rv   z"  Run manually:  litellm --config r  rf   )ra   rJ   rM   r   rq   rC   rR   rG   r   	sysconfigget_pathr/   pathr   execlpr   r~   r   )r   r   r   startscripts_dirlitellm_binr   s          r4   r   zSetupWizard._offer_start]  s6   e3DM?"E

%' 	 ((G 1+?@AAXY GI$wWX Ghj4./00B4&IJdSTU<TFCD*:,78d89:*4&89d>"#%dV56T1U0VWXhj5=/5G0H/IJK((3ggll;#4"i@	VIIK D	  	VDf'@@AB!C5IJ6{m8D6QSTUU	Vs   ,I 	J3JJr)   N)r)   ztuple[int, str])__name__
__module____qualname____doc__staticmethodrr   rn   rw   r   r   rx   r   r   r   r   boolr   r   r   ry   r   r   rz   r}   r   r   r   r2   r3   r4   rl   rl      s1    9 9 @ @0 
 
 2tDz 2 2 >s > >* # #C # #QT # #* "8d "8 "8H Md4j M MF 1d 1S#X 1 1f d s   "t "c "c " "L    * = := sCx.=  =  
	=  = B D     $ 4V$ 4Vc 4Vs 4Vt 4V 4Vr3   rl   c                  ,    t         j                          y)z>Run the interactive setup wizard. Called by `litellm --setup`.N)rl   rr   r2   r3   r4   run_setup_wizardr!    s    OOr3   r  )5r  importlib.metadatar   r/   rer   r,   r  pathlibr   typingr   r   r   r   r   r   r   r  __annotations__ImportErrorlitellm.utilsr	   r(   compiler\   r>   rO   rB   rF   rI   rL   r:   r   r   r   r   r   r5   r   r;   r@   rC   rG   rJ   rM   rP   rR   ra   rj   r   rl   r!  r2   r3   r4   <module>r*     s    	 	  
   , ,"t" * 5##]+ ?& 1W 9#/,.EF )%$?+ 4&FG.0AB);7
 ?$&67,	g=	4: =H 2::o&
!	   			F FBS B B Bc c C C S S C C C C 3 3 "# "

$# 
$# 
$  CV CVVC  G
Cs   D( (D65D6