
    AHj                    ^   U 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	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mZ d dlmZmZmZmZmZmZmZmZmZmZmZmZm Z m!Z! d dl"Z"d dl#Z#d dl$Z#d dl%m&Z&m'Z' d dl(m)Z) d dl*m+Z+m,Z,m-Z-m.Z.m/Z/m0Z0m1Z1m2Z2m3Z3m4Z4m5Z5m6Z6m7Z7m8Z8m9Z9 d dl:m;Z; d dl<m=Z= d d	l>m?Z?m@Z@mAZAmBZBmCZCmDZDmEZEmFZFmGZGmHZHmIZImJZJmKZKmLZLmMZMmNZNmOZOmPZPmQZQmRZRmSZSmTZTmUZUmVZVmWZWmXZXmYZYmZZZm[Z[m\Z\m]Z] d d
l^m_Z_m`Z` d dlambZb d dlcmdZdmeZemfZfmgZg d dlhmiZimjZj erd dlkmlZl d dlmmnZo d dlpmqZq eeoef   ZnneZneZqddddZreesef   etd<   dodZueue_u         ej                  dew       g Zxeyetd<   ej                  j                  d ej                  j                  d             	 d dl}Z}d dl~Z~d dlZd dlZd dlZd dlmZ g dZd Zd d lmZ d d!lmZ d d"lmZ d dlZd d#lmZ d d$lmZmZ d d%lmZmZ d d&lmZ d d'l*mZmZmZmZmZmZmZmZmZmZmZmZmZmZmZ d d(lmZ d d)lmZ d d*lmZ d d+lmZ d d,lmZmZ d d-lmZ d d.l:mZ d d/lmZ d d0lmZmZ d d1lmZ d d2lmZ d d2lmZ d d2lmZ d d3lmZ d d4lmZ d d5l> d d2lmZ d d6lmZ d d2lmZ d d7lmZmZ d d2lmZ d d8lmZ d d2lmZ d d2lmZ d d9lmZmZmZ d d:lmZ d d;lmZ d d<lmZ d d=lmZmZmZmZmZ d d>lmZmZmZ d d2lmZ d d2lmZ d d?lmZmZmZ d d@l^mZ d dAlmZ d d2lmZ d dBlmZmZ d dClmZ d dDlm Z mZmZmZ d dElmZmZ d dFlmZ d dGl	m
Z
 d dHlmZ d dIlmZ d d2lmZ d d2lmZ d dJlmZ d dKlmZ d dLlmZ d d2lmZ d dMlmZ d d2lmZ d d2lmZ d dNl m!Z!m"Z" d dOl#m$Z$ d d2l%mZ& d dPl'm(Z( d dQl)m*Z* d dRl+m,Z, d d2l-mZ. d dSl/m0Z0 d d2l1mZ2 d d2l3mZ4 d d2l5mZ6 d d2l7mZ8 d dTl9m:Z:m;Z; d d2l<mZ= d d2l>mZ? d d2l@mZA d d2lBmZC d d2lDmZE d d2lFmZG d dUlFmHZH d d2lImZJ d dVlKmLZLmMZMmNZN d d2lKmZO d d2lPmZQ d d2lRmZS d dWlTmUZUmVZVmWZW d d2lTmZX d d2lYmZZ d d2l[mZ\ d d2l]mZ^ d d2l_mZ` d dXlambZb d d2lcmZd d d2lemZf d d2lgmZh d dYlgmiZimjZj d d2lkmZl d dZlmmnZn d d2lmmZo d d2lpmZq d d2lrmZs d d[ltmuZu d d\lvmwZw d d]lxmyZy d d2lzmZ{ d d2l|mZ} d d2l~mZ d d^l~mZ d d_lmZ d d2lmZ d d`lmZ d dalmZ d d2lmZ d d2lmZ d d2lmZ d d2lmZ d d2lmZ d d2lmZ d d2lmZ d d2lmZ d d2lmZ d dblmZ d d2lmZ d d2lmZ d d2lmZ d d2lmZ d dclmZ d d2lmZ d ddlmZ d d2lmZ d delmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZ d d2lmZ d d2lmZ d d2lmZ d d2lmZ d d2lmZ d dflǐmȐZȐmɐZɐmʐZʐmːZ d dgl̐m͐Z͐mΐZ d dhlϐmАZ d dilѐmҐZ d djlӐmԐZԐmՐZՐm֐Z֐mאZ d dklؐmِZ d dllڐmېZېmܐZܐmݐZݐmސZ d dmlߐmZ d dnlmZ d dolmZ d dplmZmZ d dqlmZ d drlmZ d dslmZ d dtlmZmZmZ d dulmZ d dvlmZmZ d dwlcmZmZ d dslcmZ d dxlcmZmZ d dylhmZ 	 d dzlmZ d|e_        d dl Z d d}lmZ d d~lmZmZmZmZmZmZmZmZm	Z	m
Z
mZmZmZmZmZ d dlmZ d dlmZ d dlmZ d dlmZ d dlmZmZmZmZmZ d dlmZ d dl m!Z! d dl"m#Z# d dl$m%Z% d dl&m'Z'  e       Z(	 d dl)m*c m+Z+ 	 d d2l,mZ- d dl.m/Z/ e-Z( e/       Z0ee/   etd<    e       Z1 e       a2td        jg                         a4e5etd<   td        jl                  Z7ed   etd<    ejp                  d      Z9ees   etd<    e
       Z: e       Z;e9
dZ<e=etd<   n e=e9      Z< ejp                  d      Z>ees   etd<   e>
dZ?e@etd<   n e@e>      Z?e1 dZAe1 dZBe1 dZCdeA deB dZDeDdz  ZDeDdeC dz  ZDe1 dZEeDdeE dz  ZDdZFth        r ejp                  dd      ndZGth        r ejp                  ddeF deD       n	deF deD ZHd ZId ZJd ZKedefd       ZL e e        e       eGeHee1eL      Z e       ZMd dlmNZN d ZOd ZP ejp                  dd      dk(  rth        r
ePeŐ_Q        n	eOeŐ_Q         G d dej                        ZSeŐj                  eV      de	deVfd       ZU e       ZdgZV	 ej                  j                  ej                  j                  eX            ZYej                  j                  eYdd      Z[e[Z\dZ]desde5fdZ^desde5fdZ_desde5fdĄZ`desdesdeae5esf   fdǄZb ejp                  ddɫ      j                         dk(  ZdedrdːZene[Ze ejp                  d̐ee      Zf e_e[      s ej                  d͐e[ dΝ       efe[k7  Zhehr e`ef      Zi e^ef      Zjejreir ej                  dϐef        efZ\nejr eis ej                  dАef dѝ       efZ\nq ej                  dҐef dӝ        ebe[ef      \  ZmZgemrefZ\n@ ej                  dԐef dՐeg d֐e[ dם       e[Z\n ej                  dؐe[        e[Z\ e_e\      s ej                  dِe\ dڝ       e1r)e1dk7  r" ej                  e\ej                        Zpeps ej                  dܐe\ dݝ       n ej                  e\      D ]  \  ZrZsZtetD ]  Zuej                  j                  ereu      Zveuj                  dޫ      r8	  exevdd      5 Zyeyj                         Z{ddd       e{j                  e] e1       Z}e}j                  de1 d      Z} exevdd      5 Zyeyj                  e}       ddd         eŐj                  d e%ej                  j                  e\d            d       eŐj                  e] d e%ej                  j                  e\d            d       eŐj                  d e%e\d|      d       desddfdZ	  e`e\      Zi ej                  e\ej                        Zpeir ej                  de\ d       n=eps ej                  de\ d       n! ee\        ej                  de\        ej                  j                  ej                  j                  eX            ZYeŐj                  eeVd|dgdge8       eŐj                  ey       eŐj                  ew       d Z e         e       Z ejp                  d      Zees   etd<   edk7  reeŐj                  dd      d        Zd dlmZ dadadadadadad|adZdadaees   etd<   d|Zdadaee   etd<   daeey   etd<   i aeetd <   daeeeesef         etd<   dZdZdaees   etd<   dZeee'      etd<   dadaee   etd<   daed   etd<    eeSjF                  jH                        a eeSjF                  jH                        Z e(tJ        	      ZejP                  jS                  e       daee   etd
<   daeed   ees   e5f   etd<   g aees   etd<   dae=etd<   dadadae5etd<   dae5etd<   dadadadadadadadai aeesee=eeesef      f   f   etd<   dad ag Zeetd<   dZeadaeed   ef   etd<   eaeaeaeadada e       Zdaee*   etd<   daɐe5etd<   daeeq   etd<    etJ        th              adZdZdZdadadadaee   etd<   de	fdZӐd ZdefdZՐdpde5fd Z֐d! Zאd"esd#e@de@fd$Zؐd%ees   d&ees   d'ees   d(ee@   fd)Zِd"esd*esd+e@fd,Z	 dqd%ees   d'ees   d-ees   d&ees   d(ee@   d.een   d/eees      fd0Zېd1 Zdee@   fd2Zdesfd3Zސd4eyd5ee5   d6ee=   d7efd8Zߐd4eyd9eyd:eyfd;Zd9eyd:eyddfd<Zd= Z G d> d?e      Z G d@ dA      Z e       adB Z	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 drdCZdD ZdEe]dFefdGZdFedesfdHZdIedJesdFedKe5deee5f   f
dLZdEe]dFefdMZdEe]dFefdNZi fdOefdPZdQ ZdR Z G dS dT      Zej                  dU ee      gdVgW      ej                  dX ee      gdVgW       ee      dddddddfdEe]dYee5   d&ees   dZee5   d[ee5   d\ee5   d]ees   d^ees   fd_              Zej                  d` ee      gdVgW      ej                  da ee      gdVgW       ee      fdbesdEe]fdc              Zej                  dd ee      gdegW      ej                  df ee      gdegW      ej                  dg ee      gdegW      ej                  dh ee      gdegdidjdkiiel      d ee      fde	dme
dOees   dEe]fdn                            Zej                  do ee      gdpgW      ej                  dq ee      gdpgW      ej                  dr ee      gdpgW      ej                  ds ee      gdpgW      d ee      fde	dme
dOees   dEe]fdt                            Zej                  du ee      gedvgw      ej                  dx ee      gedvgw      ej                  dy ee      gedvgw      ej                  dz ee      gedvgw      d ee      fde	dme
dOees   dEe]fd{                            Zej                  d| ee      ged}gw      ej                  d~ ee      ged}gw       ee      fde	dme
dEe]fd              Zdedeedf   fdZej                  d ee      gdgW      ej                  d ee      gdgW       ee      fde	dme
dEe]fd              Zej                  d ee      gdgW      ej                  d ee      gdgW       ed       ee      fde	dme
dedEe]fd              ZeŐj                  d       ej                  dd       ej                  dd       ej                  dd       ee      fdedOees   dees   dees   fd       Z ee      dOesdees   deeesesf   df   fd       ZeŐj                  d      eŐj                  d       ej                  dd       ej                  dd       ee      fdedOesdesdees   fd              Z ej                  d ee      gdgW      ej                  d ee      gdgW       ee      fde	dme
dEe]fd              Zej                  d ee      gdgW      ej                  d ee      gdgW       ee      fde	dme
dEe]fd              Zej                  d ee      gdgW      ej                  d ee      gdgW       ee      fde	desdme
dEe]fd              Zej                  d ee      gdgW      ej                  d ee      gdgW       ee      fde	dme
dEe]fd              Zej                  d ee      gdgW      ej                  d ee      gdgW       ee      fde	desdme
dEe]fd              Zej                  d ee      gdgW      ej                  d ee      gdgW       ee      fde	desdme
dEe]fd              Zej                  d ee      gdgW      ej                  d ee      gdgW       ee      fde	desdme
dEe]fd              Zej                  d ee      gdgW      ej                  d ee      gdgW       ee      fde	desdme
dEe]fd              Z	d dl
mZ dedesdeee   ees   ees   f   fdZej                  ddg ee      geg      dpde[de5fd       Zej                  ddg ee      g      dOesfd       Zej                  ddg ee      ge      de\fd       Zdee   dEe]dee   dee   fdZdee   deRdee   fdĄZdee   dedEe]dee   fdƄZdeeQ   dedeesees   f   fdȄZdeees   ed   f   dededeesees   f   fdʄZdeRdedees   fd̄ZdEe]dededee   dee   f
d̈́Z	 dsdOeesef   dΐe5dee   deesef   fdτZ	 dqdeeesef      desdѐe=dҐe=dee   dedees   deeeesef      ee=   f   fdՄZdedee   fdׄZ	 dtdeeesef      dees   desdeeesef      fdڄZdeeesef      dѐe=dҐe=dee=   dees   deesef   fd܄Zdeeesef      d&esdededeeesef      f
d݄Zdbesdees   deaeyee=   f   fdބZej                  dߐddVg ee      gd       ee       ej                  dd       ej                  dd       ej                  dd      d eddd       eddd       ej                  dd       ej                  dd       ej                  dd       ej                  dd       ej                  dؐd      fdEe]dOees   dee5   dee5   dee5   dѐe=dҐe=dees   dees   dees   dees   dees   fd       Zej                  dddVgd ee      g       ee      dddfdEe]dees   dee   dee   fd       Zej                  dddVgd ee      g       ee      dddddfdEe]dees   dee   dee   d ees   dees   fd       Z ej                  dddVgd ee      g       ee      dddddfdEe]dees   dee   dee   d ees   dees   fd       Z!ej                  dddVgd ee      g       ee      dddddfdEe]dees   dee   dee   d ees   dees   fd       Z"dOedefd	Z#ej                  d
dVg ee      g      ej                  ddVg ee      g       ee      dfdEe]dees   fd              Z$dedees   dees   dee   fdZ%ej                  ddVg ee      g       ee      dfdEe]dees   fd       Z&ej                  dddVg ee      gd      d        Z'ej                  dddg ee      gd       ee      fdEe]fd       Z(ej                  ddg ee      gd      d ee      fde	dme
dOees   dEe]fd       Z)eŐj                  ddgd      de	fd       Z*ej                  d d      de	fd!       Z+ej                  d"d      de	fd#       Z,ej                  d$d      de	fd%       Z-ej                  d&d      de	fd'       Z.eŐj                  d(d      d)esde	fd*       Z/eŐj                  d+d      d,eJfd-       Z0eŐj                  d.d      d/        Z1eŐj                  d0d      d1        Z2eŐj                  d2d      d3        Z3ej                  d4d5g ee      geLd6       ee      fd,eMdEe]fd7       Z4ej                  d8d5g ee      geLd6       ee      fd9esdEe]fd:       Z5ej                  d;d5g ee      geLd6       ee      fd,eNdEe]fd<       Z6ej                  d=d5g ee      geLd6       ee      fd,eKdEe]fd>       Z7ej                  d?d@g ee      gd       ee      fdAeGdEe]fdB       Z8	 ej                  dCd@g ee      gd       ee      fd,eDdEe]fdD       Z9ej                  dEd@g ee      geCd6       ee      fdFesdEe]fdG       Z:ej                  dHd@g ee      gd       ee      fdIed    dEe]deeF   fdJ       Z;ej                  dKd@g ee      gd       ee      fd,eBdEe]fdL       Z<ej                  dMd@g ee      gd       ee      fd,e?dEe]fdN       Z=ej                  dOd@gd ee      gP      dQ        Z>ej                  dRd@g ee      gd      dAeGfdS       Z?ej                  dTdVg ee      gd       ee      fdEe]fdU       Z@ej                  dVdVg ee      gd       ee      fdWe=dEe]fdX       ZAej                  dVdVg ee      gd       ee      fdEe]fdY       ZBej                  dZdVg ee      gd       ee      fdEe]fd[       ZCej                  d\dVg ee      gd       ee      fdEe]fd]       ZDej                  d^dVg ee      gd       ee      fdEe]fd_       ZEej                  d`dVg ee      gd       ee      fdWe=dEe]fda       ZFej                  d`dVg ee      gd       ee      fdEe]fdb       ZGej                  dcdVg ee      gd       ee      fdEe]fdd       ZHej                  d ee      ge      de	fdf       ZIej                  dg ee      ge      dh        ZJeŐj                  e       eŐj                  e       eŐj                  e       eŐj                  e       eŐj                  e       eŐj                  e{       eŐj                  e       eŐj                  eƫ       eŐj                  e       eŐj                  e       eŐj                  e.       eŐj                  e       eŐj                  e       eŐj                  e       eŐj                  e«       eŐj                  e       eŐj                  e       eŐj                  e       eŐj                  eQ       eŐj                  e       eŐj                  e׫       eŐj                  e٫       eŐj                  e}       eŐj                  eի       eŐj                  e       eŐj                  eī       eŐj                  e       eŐj                  e&       eŐj                  eO       eŐj                  eG       eŐj                  eh       eŐj                  eo       eŐj                  eb       eŐj                  eZ       eŐj                  e^       eŐj                  eC       eŐj                  e       eŐj                  e       eŐj                  e       eŐj                  e       eŐj                  eӫ       eŐj                  e       eŐj                  e\       eŐj                  eq       eŐj                  e       eŐj                  e       eŐj                  e       eŐj                  e       eŐj                  e8       eŐj                  e       eŐj                  e       eŐj                  e       eŐj                  ef       eŐj                  eJ       eŐj                  e4       eŐj                  eX       eŐj                  eS       eŐj                  ed       eŐj                  el       eŐj                  eA       eŐj                  e`       eŐj                  eE       eŐj                  e6       eŐj                  e?       eŐj                  es       eŐj                  e(       eŐj                  e       eŐj                  eΫ       eŐj                  e=       eŐj                  eʫ       eŐj                  e2       eŐj                  dig djk      dlesde	fdm       ZMeŐj                  e1eƐn       eŐj                  eë       eŐj                  e       y# e$ rZ ede d      dZ[ww xY w# e$ r d{ZY 'w xY w# e$ r 	 d dl+Z+n# e$ r Y nw xY wY &cw xY w# e$ r dZ0Y &Jw xY w# 1 sw Y   !|xY w# 1 sw Y   !,xY w# eeef$ r Y !w xY w# e$ r%Z ej                  de\ de        Y dZ[ ?dZ[we$ r%Z ej                  de\ de        Y dZ[ hdZ[ww xY w# e$ r Y  yw xY w(u      N)datetime	timedeltatimezone)TYPE_CHECKINGAnyAsyncGeneratorDictListLiteralOptionalSetTupleUnioncastget_args
get_originget_type_hints)	BaseModelJson)uuid)AIOHTTP_CONNECTOR_LIMIT AIOHTTP_CONNECTOR_LIMIT_PER_HOSTAIOHTTP_KEEPALIVE_TIMEOUTAIOHTTP_NEEDS_CLEANUP_CLOSEDAIOHTTP_TTL_DNS_CACHEAUDIO_SPEECH_CHUNK_SIZEBASE_MCP_ROUTEDEFAULT_MAX_RECURSE_DEPTH$DEFAULT_SHARED_HEALTH_CHECK_LOCK_TTLDEFAULT_SHARED_HEALTH_CHECK_TTL DEFAULT_SLACK_ALERTING_THRESHOLD<LITELLM_EMBEDDING_PROVIDERS_SUPPORTING_INPUT_ARRAY_OF_TOKENS"LITELLM_SETTINGS_SAFE_DB_OVERRIDESLITELLM_UI_ALLOW_HEADERSLITELLM_UI_SESSION_DURATION)$_init_custom_logger_compatible_class)
safe_dumps)CallbackDeleteCallInfoCommonProxyErrorsConfigFieldDeleteConfigFieldInfoConfigFieldUpdateConfigGeneralSettings
ConfigList
ConfigYAMLEnterpriseLicenseDataFieldDetailInvitationClaimInvitationDeleteInvitationModelInvitationNewInvitationUpdateLitellm_EntityTypeLiteLLM_JWTAuthLiteLLM_TeamTableLiteLLM_UserTableLitellmUserRolesPassThroughGenericEndpointProxyErrorTypesProxyExceptionRoleBasedPermissionsSpecialModelNamesSupportedDBObjectTypeTeamDefaultSettingsTokenCountRequestTransformRequestBodyUserAPIKeyAuth)normalize_callback_namesprocess_callback_realtime_request_body)ModelResponseModelResponseStreamTextCompletionResponseTokenCountResponse)$_invalidate_model_cost_lowercase_mapload_credentials_from_list)ClientSession)Span)OpenTelemetryhttpPOSTz/v1/realtime)typemethodpathREALTIME_REQUEST_SCOPE_TEMPLATEc                 \    | d| d|j                    d|  d}||j                  |       y y )N:: 
)__name__write)messagecategoryfilenamelinenofilelinetraceback_infos          R/root/tools/cai/cai_env/lib/python3.12/site-packages/litellm/proxy/proxy_server.pyshowwarningrh      s>     z6("X->->,?r'"MN

>"     default)ra   messagesz../..)AsyncIOSchedulerzMissing dependency z$. Run `pip install 'litellm[proxy]'`)z%'The thing I wish you improved is...'z'A feature I really want is...'z*'The worst thing about this product is...'z$'This product would be better if...'z 'I don't like how this works...'z&'It would help me if you could add...'z/'This feature doesn't meet my needs because...'z&'I get frustrated when the product...'c                     d} t        j                  t              }t                t        dd| z  z   dz          t        dd| z  z   dz          t        ddj	                  |      z          t        ddj	                  d      z          t        dd| z  z   dz          t        dd| z  z   dz          t                t        d	       t                t                t                t        d
       t                t                y )N<   z[1;37m#-z#[0m z[1;37mz# {:^59} #[0mz-https://github.com/BerriAI/litellm/issues/newz/ Thank you for using LiteLLM! - Krrish & IshaanzR[1;31mGive Feedback / Get Help: https://github.com/BerriAI/litellm/issues/new[0m)randomchoicelist_of_messagesprintformat)	box_widthr`   s     rg   generate_feedback_boxrw      s    I mm,-G	G	
sY
.
;<	
sY
.
;<	,,33G<
<=	

$
$%T
U	V 

sY
.
;<	
sY
.
;<	G	
;<	G	G	G	b 
G	Gri   )defaultdict)asynccontextmanager)	lru_cache)Routerverbose_proxy_loggerverbose_router_logger)	DualCache
RedisCache)RedisClusterCache)_REALTIME_BODY_CACHE_SIZEAPSCHEDULER_COALESCEAPSCHEDULER_MAX_INSTANCESAPSCHEDULER_MISFIRE_GRACE_TIMEAPSCHEDULER_REPLACE_EXISTINGDAYS_IN_A_MONTHDEFAULT_HEALTH_CHECK_INTERVALDEFAULT_MODEL_CREATED_AT_TIMELITELLM_PROXY_ADMIN_NAME)PROMETHEUS_FALLBACK_STATS_SEND_TIME_HOURSPROXY_BATCH_POLLING_ENABLEDPROXY_BATCH_POLLING_INTERVALPROXY_BATCH_WRITE_AT!PROXY_BUDGET_RESCHEDULER_MAX_TIME!PROXY_BUDGET_RESCHEDULER_MIN_TIME)RejectedRequestError)ModifyResponseException)CustomLogger)SlackAlerting)!_get_parent_otel_span_from_kwargs get_litellm_metadata_from_kwargs)CredentialAccessor)Logging)SensitiveDataMasker)AsyncHTTPHandlerHTTPHandler)
VertexBaserouter)app)global_mcp_tool_registry)*global_agent_registry)append_agents_to_model_groupappend_agents_to_model_info)claude_code_marketplace_router)ExperimentalUIJWTTokenget_team_objectlog_db_metrics)check_response_size_is_safe)
JWTHandler)LicenseCheck)get_all_fallbacksget_complete_model_listget_key_modelsget_mcp_server_idsget_team_models)+_fetch_global_spend_with_event_coordinationuser_api_key_authuser_api_key_auth_websocket)ProxyBaseLLMRequestProcessing_is_azure_model_router_requestcreate_response)initialize_callbacks_on_proxy)init_verbose_loggers)decrypt_value_helperencrypt_value_helper)build_ui_login_form)_read_request_body_safe_get_request_headerscheck_file_size_under_limitget_form_data)!get_config_file_contents_from_gcsget_file_contents_from_s3)%remove_sensitive_info_from_deployment)
ProxyState)ResetBudgetJob)ERROR_RESPONSESSpendLogCleanup)PrismaDBExceptionHandler)ui_discovery_endpoints_router)set_fine_tuning_config)init_guardrails_v2initialize_guardrails)perform_health_check)&_PROXY_VirtualKeyModelMaxBudgetLimiter)"_OPTIONAL_PromptInjectionDetection)_ProxyDBLogger)add_litellm_data_to_request)_user_has_admin_privilegesadmin_can_invite_user)user_update)delete_verification_tokensduration_in_secondsgenerate_key_helper_fn)_add_model_to_db_add_team_model_to_db"_deduplicate_litellm_router_models)scim_router)update_teamvalidate_membership),get_disabled_non_admin_personal_key_creation)create_audit_log_for_update)InFlightRequestsMiddleware)PrometheusAuthMiddleware)set_files_config)passthrough_endpoint_router$vertex_ai_live_websocket_passthrough)!initialize_pass_through_endpoints)route_request)get_logging_payload)get_instance_fn)PrismaClientProxyLoggingProxyUpdateSpend_cache_user_row_get_docs_url_get_projected_spend_over_limit_get_redoc_url_is_projected_spend_over_limit_is_valid_team_configsget_custom_urlget_error_message_strget_server_root_pathhandle_exception_on_proxyhash_password
hash_token!migrate_passwords_to_scrypt_async model_dump_with_preserved_fieldsupdate_spend)AssistantsTypedDict
DeploymentLiteLLM_ParamsModelGroupInfo)FlowItem	Scheduler)load_aws_kms)load_google_kms)
get_secretget_secret_boolget_secret_strstr_to_bool)SlackAlertingArgs)AnthropicMessagesRequestAnthropicResponse!AnthropicResponseContentBlockTextAnthropicResponseUsageBlock)HttpxBinaryResponseContent)WorkerRegistryEntry)ModelGroupInfoProxy)DefaultTeamSSOParams#LiteLLM_UpperboundKeyGenerateParams)RealtimeQueryParams)DeploymentTypedDict)	ModelInfo)RouterGeneralSettingsSearchToolTypedDictupdateDeployment)DefaultPriorities)KeyManagementSettingsKeyManagementSystem)CredentialItemCustomHuggingfaceTokenizer)RawRequestTypedDictStandardLoggingPayload)-_add_custom_logger_callback_to_specific_event)versionz0.0.0T)r   )DependsFastAPIFileFormHeaderHTTPExceptionPathQueryRequestResponse
UploadFile	WebSocketWebSocketDisconnectapplicationsstatus)jsonable_encoder)CORSMiddlewareget_swagger_ui_html)get_openapi)FileResponseJSONResponseORJSONResponseRedirectResponseStreamingResponse)	APIRouter)OAuth2PasswordBearer)APIKeyHeader)StaticFiles)AgentConfig)EnterpriseProxyConfigenterprise_proxy_configpremium_userr1   premium_user_data+LITELLM_GLOBAL_MAX_PARALLEL_REQUEST_RETRIES'global_max_parallel_request_retries_env   #global_max_parallel_request_retries1LITELLM_GLOBAL_MAX_PARALLEL_REQUEST_RETRY_TIMEOUT-global_max_parallel_request_retry_timeout_envg      N@)global_max_parallel_request_retry_timeoutz/uiz/fallback/loginz/ui/model_hub_tableu(   👉 [```LiteLLM Admin Panel on /ui```](zI). Create, Edit Keys with SSO. Having issues? Try [```Fallback Login```]()uB   

💸 [```LiteLLM Model Cost Map```](https://models.litellm.ai/).u!   

🔎 [```LiteLLM Model Hub```](z[). See available models on the proxy. [**Docs**](https://docs.litellm.ai/docs/proxy/ai_hub)z/ui/chatu   

💬 [```LiteLLM Chat UI```](zN). ChatGPT-like interface for your users to chat with AI models and MCP tools.zr[**Customize Swagger Docs**](https://docs.litellm.ai/docs/proxy/enterprise#swagger-docs---custom-routes--branding)
DOCS_TITLEzLiteLLM APIDOCS_DESCRIPTIONzJEnterprise Edition 

Proxy Server to call 100+ LLMs in the OpenAI format. 

z5Proxy Server to call 100+ LLMs in the OpenAI format. c                  8    d a d ad ad ad ad ad ad ad ad a	d a
d ad ay N)
master_keyuser_config_file_pathotel_logginguser_custom_authuser_custom_auth_pathuser_custom_key_generateuser_custom_sso"user_custom_ui_sso_sign_in_handleruse_background_health_checksuse_shared_health_checkhealth_check_intervalhealth_check_concurrencyprisma_client ri   rg   cleanup_router_config_variablesr_    sN     J L #O)-&#' " #Mri   c                  b  K   t        j                  d       t        r1t        j                  d       t        j	                          d {    t
        j                  &t
        j                  j	                          d {    t        j                          d {    t        t        j                          d {    dt
        j                  v r.	 ddlm}  | | j                  j                          t!                y t!                y 7 7 7 u7 U# t        $ r Y t!                y w xY ww)Nz"Shutting down LiteLLM Proxy ServerzDisconnecting from Prismalangfuser   langFuseLogger)r}   infor]  debug
disconnectlitellmcachejwt_handlerclosedb_writer_clientsuccess_callbacklitellm.utilsrc  Langfuseflush	Exceptionr_  rb  s    rg   proxy_shutdown_eventrq    s     BC""#>?&&(((}} mm&&(((



#$$&&& W---	4)''--/ $%#%/ 	) 	) 	'  	 $%	sl   AD/
D5D/ DD/D!D/>D?D/"D 8D/D/D/D/	D,D/+D,,D/c            	      x  K   	 ddl m} m} t        t        d}t
        rd|d<   t        dkD  r	t        |d<   t        dkD  r	t        |d<    |di |} | |      }t        j                  d	t        |       d
t         dt         d       |S # t        $ r#}t        j                  d| d       Y d}~yd}~ww xY ww)zNInitialize shared aiohttp session for connection reuse with connection limits.r   )rQ   TCPConnector)keepalive_timeoutttl_dns_cacheTenable_cleanup_closedlimitlimit_per_host)	connectorzJSESSION REUSE: Created shared aiohttp session for connection pooling (ID: z, limit=z, limit_per_host=rK  z)Failed to create shared aiohttp session: z#. Continuing without session reuse.Nr^  )aiohttprQ   rs  r   r   r   r   r   r}   rd  idrp  warning)rQ   rs  connector_kwargsry  sessiones         rg   "_initialize_shared_aiohttp_sessionr    s     7 ";2,
 (8<45"Q&(?W%+a/1Q-. 4#34	)4!!XY[\cYdXe f,-->?_>``ac	
  $$7s:]^	
 	s/   B:BB 
B:	B7B2-B:2B77B:r   c                n  K   dd l }t                t        j                  j	                  dd      }|r|j                  d      D ]  }|j                         }|s	 d|vrt        d| d      |j                  dd      \  }}t        j                  |      }t        ||      }t        j                  |      r |        d {    n |        t        j                  d	|        t        j$                  dj'                  t(                     t(        du rt*        j-                         at/        d      at3        d      }	t/        d      }
t        j$                  d|	       |
`t        j4                  j7                  |
      r`t8        j;                  |
      rIt8        j=                  t>        |
       d {   \  aa a!n |	tE        |	tF              r]t        j4                  j7                  |	      r>t8        j;                  |	      r(t8        j=                  t>        |	       d {   \  aa a!nt        j                  j	                  d      8tE        |	tF              r(t8        j=                  t>        |	       d {   \  aa a!nYtE        |	tH              rtK        d.i |	 d {    n5 |jL                  |	      }	tE        |	tH              rtK        d.i |	 d {    tN        4t3        dd       }tP        jS                  |tT        tV               d {   a'tN        d }tY        jZ                   |              tP        j]                  t>        tT        t^               tP        ja                  tB        t^               	 t        j$                  d       t8        jc                         }|j	                  di       }t        j$                  dte        |jg                                       tP        ji                  t>        |       d {    t        j$                  d       tP        jk                  tB        tN        tV        !       tl        tl        jo                  t>        "       t        j$                  d#tN               tN        dtp        jr                  dkD  rQtP        ju                  tv        $       tY        jZ                  tP        jy                  tv        tV        tN        %             tN        stP        j{                  tB        tN        t|        t~        t        tT        &       d {    tP        j                          d {    tP        j                          d {    t        rtY        jZ                  t                      tP        j                          tP        j                          t                d {   aHd  t        2	 t        j                          d {    t        j                  d'       tN        Qt        tN        d)      rAt        tN        j                  d*      r'	 tN        j                  j                          d {    tN        -t        tN        d,      r	 tN        j                          d {    t                d {    y 7 # t         $ r}t        j"                  d
||        d }~ww xY w7 7 7 P7 +7 7 7 # t         $ r%}t        j"                  d| d        Y d }~d }~ww xY w7 7 7 7 Z7 5# t         $ r#}t        j"                  d(|        Y d }~Ed }~ww xY w7 # t         $ r#}t        j"                  d+|        Y d }~d }~ww xY w7 # t         $ r#}t        j"                  d-|        Y d }~d }~ww xY w7 w)/Nr   LITELLM_WORKER_STARTUP_HOOKS ,r[   zInvalid hook spec 'z1': expected format is 'module.path:function_name'   z.Worker startup hook '%s' executed successfullyz#Worker startup hook '%s' failed: %szElitellm.proxy.proxy_server.py::startup() - CHECKING PREMIUM USER - {}FLITELLM_MASTER_KEYWORKER_CONFIGCONFIG_FILE_PATHzworker_config: %sconfig_file_pathr   r  LITELLM_CONFIG_BUCKET_NAMEDATABASE_URL)database_urlproxy_logging_objuser_api_key_cachec                     K   	 t        t               d {   } t        j                  d|         y 7 # t        $ r"}t        j
                  d|        Y d }~y d }~ww xY ww)NzPassword migration: zPassword migration skipped: )r   r]  r}   rd  rp  r|  )resultr  s     rg   _run_pw_migrationz.proxy_startup_event.<locals>._run_pw_migrationl  s_     Q@OO$)),@*IJ P Q$,,/KA3-OPPQs6   A$6 46 A$6 	A!AA$A!!A$)
llm_routerr  redis_usage_cache)general_settingsr  z(About to initialize semantic tool filterlitellm_settingszlitellm_settings keys = )r  r  z)After semantic tool filter initializationzSemantic filter init failed: Texc_info)r  r]  r  r   zprisma_client: %s)litellm_proxy_budget_name)litellm_proxy_admin_namer  r]  )r  r]  !proxy_budget_rescheduler_min_time!proxy_budget_rescheduler_max_timeproxy_batch_write_atr  z,SESSION REUSE: Closed shared aiohttp sessionz&Error closing shared aiohttp session: dbstop_token_refresh_taskz#Error stopping token refresh task: stop_db_health_watchdog_taskz(Error stopping DB health watchdog task: r^  )Ojsonr   osenvirongetsplitstrip
ValueErrorrsplit	importlibimport_modulegetattrinspectiscoroutinefunctionr}   rd  rp  errorre  ru   rB  _license_check
is_premiumr  rQ  r  rX   isfileproxy_configis_yamlload_configr  llm_model_listr  
isinstancestrdict
initializeloadsr]  ProxyStartupEvent_setup_prisma_clientr  r  asynciocreate_task_initialize_startup_loggingr  )_validate_redis_transaction_buffer_configget_config_statelistkeys _initialize_semantic_tool_filter_initialize_jwt_authprompt_injection_detection_objupdate_environmentrg  
max_budget_add_proxy_budget_to_dbr  _warm_global_spend_cache$initialize_scheduled_background_jobsr  r  r  "_update_default_team_member_budget%_sync_ui_settings_to_general_settingsrY  _run_background_health_check_init_dd_tracer_init_pyroscoper  shared_aiohttp_sessionrj  hasattrr  r  r  rq  )r   r  _startup_hooks_env
_hook_spec_module_path
_func_name_module_hook_fnr  worker_configenv_config_yaml_db_urlr  _config_litellm_settingss                  rg   proxy_startup_eventr    s      (FK,2237 	J#))+Jj($-j\9jk  ,6+<+<S!+D(j#11,?"7J7..x8"*$$J$))Dj!	4 OVV	

 u%002   45J0:?0KM%34F%GO2MB"77>>/*|/C/C, 0D 0
 #..!O /  	  
	"}c*}-$$m$D #..!M /  	  ZZ^^89E*3K
 #..!M /  	  t,-}--- 'DJJ}5M-. 1=111 !+ND!A/DD /1 E 
 
  	Q 	-/011++ 2  ??)+ @ W""#MN//1#KK(:B?""&t,=,B,B,D'E&FG	
  @@!. A 
 	
 	
 	""#NO
 **)#- +  &1&999L2MB W%7%7!%;11&> 	2 	
 	66)A#5+ 7 	
  DD-'.O.O!5/ E 
 	
 	
  BBDDD  EEGGG $(*	

 %%' %%' $F#GG 
 )	U(..000 %%&TU 	!M4(M$$&?@	R""::<<<
  W5&	W<<>>> 
   U %  $**9:q 	< .
 2

H	

  W""%B1##FQUVVW8	
 	E 	H H 1 	U &&)OPQs'STT	U = 	R &&)LQC'PQQ	R ? 	W &&)QRSQT'UVV	W !s  A^5A(Z#Z "Z#&C^5:[;A0^5+[,A^5['^5*[+5^5 [!9^5[A*^5B[! [[! (D^5,\-^5\	^5$\%A^5\^5\! )\*\! 0^54!] ]] ^51^ ^	^ ^5^2^5 Z##	[	,[[		^5^5^5^5^5^5[! !	\*\
^5
\^5^5^5^5\! !	]*]^5]^5] 	]>]93^59]>>^5^ 	^/^*$^5*^//^5)docs_url	redoc_urltitledescriptionr!  	root_pathlifespan)APIWebSocketRoutec            	         t         j                  rt         j                  S ddlm}   | t        t         j
                  t         j                  t         j                  t         j                        }t         j                  D cg c]  }t        |t              s| }}|D ]  }|j                  j                  d      d   j                  d      }g }	 t        |d      rX|j                  Lt!        |j                  dg       }|r3|D ].  }|j#                  |j$                  d|j&                  d	d
id       0 dd|j$                  xs | dd|j$                  xs |j-                  dd       |dddiidgdi|d   |<    ddlm} |j3                  |      }t4        rddt4        j7                  d      z   ig|d<   |t         _        t         j                  S c c}w # t(        t*        f$ r Y w xY w)Nr   )get_openapi_schema_with_compat)get_openapi_funcr  r!  r  routes{?	dependantquery_paramsqueryrV   string)nameinrequiredschemar  zWebSocket: zWebSocket connection endpoint
websocket_/_101r  zWebSocket Protocol Switchedr-  )summaryr  operationId
parameters	responsestagspathsCustomOpenAPISpecurlservers)r   openapi_schema0litellm.proxy.common_utils.openapi_schema_compatr  r5  r  r!  r  r  r  r  rX   r  rstripr  r  r  appendr  r  AttributeError	TypeErrorreplace.litellm.proxy.common_utils.custom_openapi_specr   add_llm_api_request_schema_bodyserver_root_pathr  )	r  r  routewebsocket_routes	base_pathr  r  paramr   s	            rg   get_openapi_schemar    s   
!!! 4$iiOOzzN ::E;L)M 
 " #
JJ$$S)!,33C8	 
	uk*u/J&uK!- 
"))(-

&-,1NN$*H+"		
  ()@y(AB>!+EJJ,U):K:KCQT:U+VW(#m5R%ST$	.
w	*5#
L Q&FF~VN &+S3C3I3I#3N-N%O$Py!'Ci6 	* 		s   GGA$GG.-G.c                  x   t         j                  rt         j                  S t               } t        j                  j
                  }i }|D ]  }|| d   v s| d   |   ||<    || d<   ddlm} |j                  |       } t        rddt        j                  d      z   ig| d<   | t         _        t         j                  S )Nr  r   r  r  r  r  )r   r  r  LiteLLMRoutesopenai_routesvaluer
  r   r  r  r  )r  r  paths_to_includer  r   s        rg   custom_openapir  D  s    
!!!')N "//55M EN7++&4W&=e&DU#E /N7 Q&FF~VN &+S3C3I3I#3N-N%O$Py!'Cri   DOCS_FILTEREDFalseTruec                       e Zd ZdZy)UserAPIKeyCacheTTLEnumrn   N)r^   
__module____qualname__in_memory_cache_ttlr^  ri   rg   r  r  e  s    ri   r  requestexcc                    K   |j                   }|j                         }t        |j                  rt	        |j                        nt
        j                  d|i|      S w)Nr  )status_codecontentheaders)r%  to_dictr7  codeintr0  HTTP_500_INTERNAL_SERVER_ERROR)r   r!  r%  
error_dicts       rg   openai_exception_handlerr+  i  sM      kkGJ XXCM6+P+P*% s   AAr   _experimentaloutz/litellm-asset-prefixrX   returnc                     	 t         j                  j                  |       xr t        t        j                  |             S # t
        $ r Y yw xY w)NF)r  rX   isdiranyscandirFileNotFoundError)rX   s    rg   _dir_has_contentr4    s?    	77==&@3rzz$/?+@@  		s   >A 	AAui_pathc                 @   t         j                  j                  |       syt         j                  j                  t         j                  j	                  | d            syt         j                  j	                  | d      }t         j                  j                  |      syy)a  
        Verify UI directory has minimum required structure.

        Checks for:
        - Directory exists
        - Has index.html (main entry point)
        - Has _next directory (Next.js assets)

        Returns True if UI directory appears valid and servable.
        F
index.html_nextT)r  rX   r0  existsjoin)r5  next_dirs     rg   _validate_ui_directoryr<    sg     ww}}W% ww~~bggll7LAB 77<<1ww}}X&ri   ui_dirc                 L   t         j                  j                  |       syt         j                  j                  | d      }t         j                  j	                  |      rt        j                  d|        yt         j                  j	                  t         j                  j                  | d            sy	 t        j                  |       D ]  }|j                         s|j                  j                  d      r0t         j                  j                  |j                  d      }t         j                  j	                  |      szt        j                  d|j                   d        y 	 y# t        t        f$ r%}t        j                  d	|  d
|        Y d}~yd}~ww xY w)ad  
        Detect if UI directory is already pre-restructured and ready to serve.

        Returns True if:
        1. Marker file .litellm_ui_ready exists (created by Dockerfile), OR
        2. Restructuring pattern detected (subdirectories with index.html inside)

        This allows skipping copy/restructure operations on read-only filesystems.
        Fz.litellm_ui_readyzFound UI ready marker: Tr7  r  z,Detected restructured UI via pattern: found z/index.htmlzCould not scan z for restructuring detection: N)r  rX   r0  r:  r9  r}   re  r2  is_dirr  
startswithPermissionErrorOSError)r=  marker_fileentry
index_pathr  s        rg   _is_ui_pre_restructuredrF    s>    ww}}V$ ggll6+>?77>>+& &&)@'NO ww~~bggll6<@A	F+ $<<>%***?*?*D!#ejj,!GJww~~j1,22J5::,Vab  $$    ) 	 &&!&)GsK 		s1   8(E/ !E/ =A	E/ $E/ ,E/ /F#>FF#source_pathtarget_pathc                    	 t        j                  |d       t        |      s<t        |       r1t        j                  | |d       t        j                  d|        yy# t        t        f$ r}dt        |      fcY d}~S d}~ww xY w)	z|
        Attempt to populate target UI directory from source.

        Returns: (success: bool, error_message: str)
        Texist_ok)dirs_exist_okzSuccessfully populated UI at )Tr  )Fz(Source or target directory state invalidFN)
r  makedirsr4  shutilcopytreer}   rd  rA  rB  r  )rG  rH  r  s      rg   _try_populate_ui_directoryrP    s{    	!KKd3#K05Ek5R"&
 %)),I+*WXH) 	!#a&= 	!s   AA! !B0B<BBLITELLM_NON_ROOTr  truez/var/lib/litellm/uiLITELLM_UI_PATHzPackaged UI at z9 is invalid or incomplete. UI may not function correctly.zUsing pre-restructured UI at zUI at zT has content but is not properly restructured. Will attempt to restructure in place.zUI not found at z*. Attempting to populate from packaged UI.zFailed to populate UI at r\   z!. Falling back to packaged UI at zm. For read-only deployments, pre-build UI in Dockerfile or set LITELLM_UI_PATH to a writable emptyDir volume.zUsing packaged UI directory: zSelected UI path z5 is invalid or incomplete. UI may not work correctly.r  z4Cannot apply server_root_path replacements to UI at zz: path is not writable. Ensure server_root_path is '/' or pre-process UI files in Dockerfile with custom server_root_path.)	z.pngz.jpgz.jpegz.gifz.icoz.woffz.woff2z.ttfz.eotrzutf-8)encodingz&/litellm/.well-known/litellm-ui-configz/.well-known/litellm-ui-configwz/_nextr8  	directorynext_staticr  )rX  htmluiui_rootc                 Z   t        j                  |       D ]  \  }}}t         j                  j                  ||       }|dk(  rdn!|j	                  t         j
                        d   }|dv rV|D ]  }|j                  d      r|dk(  rt         j                  j                  ||      }t         j                  j                  |      d   }t         j                  j                  |d      }	t        j                  |d       	 t        j                  ||	         y	# t        $ r Y w xY w)
zCEnsure each exported HTML route is available as <route>/index.html..r  r   >   litellm-asset-prefixr8  z.htmlr7  TrJ  N)r  walkrX   relpathr  sependswithr:  splitextrM  r	  r3  )
r]  current_rootr  filesrel_rootfirst_segmentrb   	file_path
target_dirrH  s
             rg   _restructure_ui_html_filesrl  |  s    ')ggg&6 	"L!Uww|W=H"*c/Bx~~bff7Ma7PM  AA! ((1X5MGGLLx@	WW--i8;
 ggll:|DJ6JJy+6	& ) s   D	D*)D*zSkipping UI restructuring: z is already pre-restructuredzCannot restructure UI at z: path is not writable. UI may not work correctly for extensionless routes. Pre-build and restructure UI in Dockerfile for read-only deployments.zRestructured UI directory: z2Permission error while restructuring UI directory z'Error while restructuring UI directory )allow_originsallow_credentialsallow_methodsallow_headersexpose_headersc                     t         j                  j                  t        d      } t        dnt        }|j                  d      s|dz   }|dz   t        j                  dt        |       d       fd}|t        _
        y )Nswaggerr  z/swaggerrW  rZ  c                  8    t        | i | d d ddS )Nz/swagger-ui-bundle.jsz/swagger-ui.cssz/favicon.png)swagger_js_urlswagger_css_urlswagger_favicon_urlr3  )argskwargscustom_root_path_swagger_paths     rg   swagger_monkey_patchz.mount_swagger_ui.<locals>.swagger_monkey_patch  sD    "

 <<<QR<=_M#@"A N
 	
ri   )r  rX   r:  current_dirr  rd  r   mountr>  r/  r4  )swagger_directoryswagger_pathr{  rz  s      @rg   mount_swagger_uir    so    [)<*238HL  %#c)$09$<!IIj+0ABIS
 (<L$ri   ROOT_REDIRECT_URLroot_redirect_urlF)include_in_schemac                  *   K   t        t              S w)Nr  )r9  r  r^  ri   rg   root_redirectr    s     $566s   )r	   rR  r  r  r  config_passthrough_endpointszapi_log.jsonrQ  config_agentsr]  rQ   r  )default_in_memory_ttl)
dual_cacher  allpolling_via_cache_enablednative_background_mode  polling_cache_ttl_pkce_no_redis_warning_emitted_cp_no_redis_warning_emittedhealth_check_resultsqueuezlitellm-proxy-budget)adminr  ui_access_moder  store_model_in_dbopen_telemetry_logger)r  rB  rk  c                 L  K   t        j                          }t        j                          |z
  dk  rnt        j                  d       d{    | j                          d{   r|j	                          t        dd      t        j                          |z
  dk  rmyy7 V7 @w)am  
    Asynchronously checks if the request is disconnected at regular intervals.
    If the request is disconnected
    - cancel the litellm.router task
    - raises an HTTPException with status code 499 and detail "Client disconnected the request".

    Parameters:
    - request: Request: The request object to check for disconnection.
    Returns:
    - None
    X  r  Ni  zClient disconnected the requestr#  detail)timer  sleepis_disconnectedcancelr'  )r   llm_api_call_task
start_times      rg   check_request_disconnectionr  L  s      J
))+

"S
(mmA((*** $$&8  ))+

"S
(*s*   AB$	B 
B$!B"";B$B$"B$c                     ddl m} t        |       }|t        u r!t	        |       D ]  }t        ||      s|c S  yt        | t              rt        | t              r| S y)CResolve the actual TypedDict class from a potentially wrapped type.r   )_TypedDictMetaN)typing_extensionsr  r   r   r   r  rV   r  )typr  originargs       rg   _resolve_typed_dict_typer  h  sY    0_FC= 	C#~.
	
  
C	:c4#8
ri   c                 
   t        |       }g }|t        u rJt        |       D ]:  }|t        |t	        d            rdt        |      vs*|j                  |       < |S t        | t              rt        | t              r| gS |S )r  NNoneType)r   r   r   r  rV   r  r  r   )r  r  typsr  s       rg   _resolve_pydantic_typer  v  s}    _FDC= 	!C"3T
3c#h.C 	! K 
C	:c9#=uKri   use_azure_key_vaultc                 F   | du ry 	 ddl m} ddlm} t	        j
                  dd       }|t        d       |       } |||      }|t        _        t        j                  t        _        y # t        $ r+}t        |      }t        j                  d|       Y d }~y d }~ww xY w)	NFr   )DefaultAzureCredential)SecretClientAZURE_KEY_VAULT_URIzMError when loading keys from Azure Key Vault: AZURE_KEY_VAULT_URI is not set.)	vault_url
credentialztError when loading keys from Azure Key Vault: %s .Ensure you run `pip install azure-identity azure-keyvault-secrets`)azure.identityr  azure.keyvault.secretsr  r  getenvrp  rg  secret_manager_clientr  AZURE_KEY_VAULT_key_management_systemr  r}   	exception)r  r  r  KVUrir  clientr  
_error_strs           rg   load_from_azure_key_vaultr    s    e#
97 		/6=_  ,-
 *E(.%)<)L)L& 
V
&& C	
 	

s   A$A, ,	B 5!BB c                      t         Ot        j                  j                  t	                      t        j                  j                  t	                      y y rP  )r]  rg  logging_callback_manageradd_litellm_callbackr   "add_litellm_async_success_callbackr^  ri   rg   cost_trackingr    s>     ((==n>NO((KK	
 !ri   counter_keyfallback_spendc                 T  K   t         j                  7	 t         j                  j                  |        d{   }|t        |      S 	 t         j                  j                  |       }|t        |      S |S 7 A# t        $ r!}t        j                  d| |       Y d}~Vd}~ww xY ww)a  
    Read current spend from the cross-pod spend counter.

    Reads Redis FIRST (authoritative cross-pod value), not DualCache's
    async_get_cache which returns in-memory first. This is critical:
    DualCache.async_get_cache returns stale per-pod values because each
    pod's in-memory cache is only updated by that pod's own increments.

    Fallback chain:
    1. Redis counter (cross-pod, authoritative)
    2. In-memory counter (single-instance or Redis failure)
    3. Cached object's .spend from DB (cold start, no counter yet)
    NkeyzJget_current_spend: Redis read failed for %s, falling back to in-memory: %s)	spend_counter_cacheredis_cacheasync_get_cachefloatrp  r}   re  in_memory_cache	get_cache)r  r  valr  s       rg   get_current_spendr    s      &&2	+77GG H  C Sz!  
-
-
7
7K
7
HC
Sz %
  	 &&\ 	s>   B(#A; A9A; 1B(9A; ;	B%B B( B%%B(tokenteam_iduser_idresponse_costc                 H  K   ||dk(  ry| Ht        | t              r| j                  d      rt        |       n| }t	        d| ||       d{    |t	        d| d| |       d{    |&|#t	        d	| d
| d| d
| |       d{    yyy7 K7 /7 w)a  
    Atomically increment spend counters for budget enforcement.

    Uses spend_counter_cache (DualCache with Redis backend when available)
    so counters are shared across all pods. Budget check functions read
    from these counters via get_current_spend() (Redis-first).

    Awaited (not create_task) in the cost callback, so the counter is
    updated before the next request's auth check runs.
    Nr   sk-r  z
spend:key:)r  source_cache_key	incrementzspend:team:zteam_id:zspend:team_member:r[   zteam_membership:)r  r  r@  r   !_init_and_increment_spend_counter)r  r  r  r  hashed_tokens        rg   increment_spend_countersr    s        2 %%%*:*:5*A U# 	
 0$\N3)#
 	
 	
 /%gY/'y1#
 	
 	
 w2/,WIQwi@/y'C#
 	
 	
  3	
	
	
s6   AB"BB".B/%B"B B"B" B"r  r  c                   K   t         j                  |        d{   }|~t        j                  |       d{   }d}|8t        |t              r|j                  dd      xs d}nt        |dd      xs d}|dkD  rt         j                  | |       d{    t         j                  | |       d{    y7 7 7 (7 w)u  
    Initialize counter from cached object's DB-loaded spend if not yet set,
    then atomically increment in both in-memory and Redis.

    On first access per pod:
    1. Check spend_counter_cache (in-memory -> Redis via DualCache for init check)
    2. If not found anywhere, read base spend from user_api_key_cache (DB-loaded object)
    3. Seed counter via async_increment_cache (not async_set_cache) to avoid a
       check-then-set race: if two pods cold-start simultaneously, both may see
       the counter as absent and seed it. Using increment instead of set means
       the worst case is over-counting (conservative — blocks slightly early)
       rather than under-counting (would allow overspend).
    4. Increment atomically (both in-memory + Redis)
    r  N        spendr   r  r  )r  r  r  r  r  r  r  async_increment_cache)r  r  r  currentsource
base_spends         rg   r  r  	  s     & (77K7HHG)99>N9OO
&$'#ZZ5<
$VWc:Ac
>%;;z <    
3
3y 4    IOsD   C	CC	CAC	CC	;C<C	C	C	C	end_user_idparent_otel_spanr  c                   K   g dt         dt        ffd}fd}fd}	fd}
fd}|  || 	       d{     |        d{     |	        d{     |
        d{     |        d{    t        j                  t        j                  d
|             y7 t7 e7 V7 G7 8w)z`
    Use this to update the cache with new user spend.

    Put any alerting logic in here.
    r  r  c           
        K   t        | t              r| j                  d      rt        |       }n| }t	        j
                  d|       t        j                  |       d {   }t	        j
                  d|        |y |j                  }||z   }|j                  du r|j                  t        ||j                  d         d	u rt        ||j                  j                  dd             \  }}|j                  j                  dt        d
            }t        |j                   xs d||j"                  ||j$                  ||t&        j(                        }	t+        j,                  t.        j1                  d|	             |'t3        |dd       |j4                  xs d}
|
|z   |_        |'t3        |dd       |j6                  xs d}||z   |_        ||_        j9                  ||f       y 7 w)Nr  r  z"_update_key_cache: hashed_token=%sr  z&_update_key_cache: existing_spend_obj=Fsoft_budget)current_spendsoft_budget_limitTinfr  )r  r  	key_aliasr  r  projected_spendprojected_exceeded_dateevent_groupprojected_limit_exceeded)rV   	user_info
team_spendr   team_member_spend)r  r  r@  r   r}   re  r  r  r  soft_budget_cooldownlitellm_budget_tabler   r   r  r  r)   r  r  r  r8   KEYr  r  r  budget_alertsr  r  r  r  )r  r  r  existing_spend_objexisting_spend	new_spendr  r  
soft_limit	call_infoexisting_team_spendexisting_team_member_spendvalues_to_update_in_caches               rg   _update_key_cachez'update_cache.<locals>._update_key_cacheA  s&    eS!e&6&6u&=%E2L L""#GVBTBdBdiuBdBv<v""45G4HI	
 %/55N"]2	 33u<"77C."+&8&M&M%'  8W'"4"I"I"M"M!4#84O4 ,@@DDuU|J !(..4",66%*22 /(?.22	I !//3' 0  **L$?K"4"?"?"D1,?-,O) **,?FR);)M)M)RQR& +]: 0
 $- !((,8J)KLS =ws   A G6#G3$FG6c            	        K   	g} 	 | D ]  }|t         j                  |       d {   }| y t        j                  d| d        t	        |t
              r|d   }n|j                  }|z   }t	        |t
              r||d<   
j                  ||f       ||_        
j                  ||j                         f        t         j                  dj                  t                     d {   }|y /|,|z   }
j                  dj                  t              |f       y y y 7 7 <# t        $ r>}t        j                  d	t        |      t        j                                Y d }~y d }~ww xY ww)Nr  z!_update_user_db: existing spend: ; response_cost: r  {}:spendzSpend tracking - failed to update user spend in cache. Budget enforcement may use stale spend values. user_id=%s, response_cost=%s - %s
%s)r  r  r}   re  r  r  r  r  r  ru   r  rp  r|  r  	traceback
format_exc)user_ids_idr  r  r  global_proxy_spendr  r  r  r  r  s           rg   _update_user_cachez(update_cache.<locals>._update_user_cache  s    90	 W;+=+M+MRU+M+V%V"%-$**78J7KK\]j\kl 0$7%7%@N%7%=%=N*]:	 0$72;&w/-44c;M5NO/8&,-44c;M;R;R;T5UV3W6 (:'I'I%%&>? (J ( " ")*/A/M.>	)00&&'?@)L 0N*; &W."  		 ((8 A$$& 		sg   E<!D2 D-D2 E<CD2 3D04D2 :E<;/D2 *E<-D2 0D2 2	E9;4E4/E<4E99E<c            	      F  K   y dj                        } 	 t        j                  |        d {   }|y t        j                  d| d        |d}n"t        |t              r|d   }n|j                  }|z   }t        |t              r||d<   j                  | |f       y ||_        j                  | |j                         f       y 7 # t        $ r>}t        j                  dt        |      t        j                                Y d }~y d }~ww xY ww)Nzend_user_id:{}r  z%_update_end_user_db: existing spend: r  r   r  zSpend tracking - failed to update end user spend in cache. Budget enforcement may use stale spend values. end_user_id=%s, response_cost=%s - %s
%s)ru   r  r  r}   re  r  r  r  r  r  rp  r|  r  r  r  )r
  r  r  r  r  r  r  r  s        rg   _update_end_user_cachez,update_cache.<locals>._update_end_user_cache  sB    -"7%%k2$	'9'I'Ic'I'R!R!)  &&78J7KK\]j\kl ")!"0$7%7%@N%7%=%=N&6I ,d3.7"7+)00#7I1JK+4"()00#7I7N7N7P1QR1 "S2  		 ((< A$$& 		sU   D!C CC D!A/C +D!,(C D!C 	D 4DD!DD!c            	      2  K   y dj                        } 	 t        j                  |        d {   }|y t        j                  d| d        |d}n"t        |t              r|d   }n|j                  }|d}|z   }t        |t              r||d<   j                  | |f       y ||_        j                  | |f       y 7 # t        $ r>}t        j                  dt        |      t        j                                Y d }~y d }~ww xY ww)Nz
team_id:{}r  z!_update_team_db: existing spend: r  r  r  zSpend tracking - failed to update team spend in cache. Budget enforcement may use stale spend values. team_id=%s, response_cost=%s - %s
%s)ru   r  r  r}   re  r  r  r  r  rp  r|  r  r  r  )r
  r  r  r  r  r  r  r  s        rg   _update_team_cachez(update_cache.<locals>._update_team_cache  sG    ?m3!!'*(	 )88S8AA  ") &&34F3GGXYfXgh ")250$7%7%@N%7%=%=N%!$&6I ,d3.7"7+)00#7I1JK+4"()00#7I1JK5 B6  		 ((8 A$$& 		sU   DC CC DA3C /D0C 
DC 	D4D
DDDc            	      n  K   y	 D ]  } | rt        | t              sd|  }t        j                  |       d{   }|<t	        j
                  d|  d| d        t        |t              r|j                  dd      xs d}nt        |dd      xs d}|z   }t        |t              r||d<   j                  ||f       ||_
        j                  ||f        y7 # t        $ r>}t	        j                  d	t        |      t        j                                Y d}~yd}~ww xY ww)
z:
        Update the tag cache with the new spend.
        Nztag:r  z*_update_tag_cache: existing spend for tag=r\   r  r  r   zSpend tracking - failed to update tag spend in cache. Budget enforcement may use stale spend values. tags=%s, response_cost=%s - %s
%s)r  r  r  r  r}   re  r  r  r  r  r  rp  r|  r  r  )	tag_name	cache_keyexisting_tag_objr  r  r  r  r  r  s	         rg   _update_tag_cachez'update_cache.<locals>._update_tag_cache&  sp     <=0*	  Tz(C'@"8*-	);)K)K! *L * $  $+$**@
"M]L^^op}o~ .5%5%9%9'1%E%JN%,-=w%J%OaN +]:	 .509$W--44iAQ5RS-6$*-44iAQ5RS?T$4  		 ((5 A$$& 		sA   D56C+  C)B'C+ (D5)C+ +	D244D-(D5-D22D5N)r  r  rn   )
cache_listttllitellm_parent_otel_span)r  r  r  r  r  async_set_cache_pipeline)r  r  r  r  r  r  r  r  r  r  r  r  r  s    ```` `     @rg   update_cacher  /  s      8:PMs PM5 PMf3l)X-`1f ]6e=III """$&&& """!!!330%5 	4 	
 	J 	# 	' 	# 	"sZ   AC	
B?C	CC	,C-C	=C>C	C1C	C	C	C	C	c                      	 ddg} t        t        j                  d      5 }t        j                  | ||       d d d        y # 1 sw Y   y xY w# t
        $ r#}t        j                  d| d       Y d }~y d }~ww xY w)NollamaserverV  )stdoutstderrzd
            LiteLLM Warning: proxy started with `ollama` model
`ollama serve` failed with Exceptionz). 
Ensure you run `ollama serve`
        )openr  devnull
subprocessPopenrp  r}   re  )commandr!  r  s      rg   run_ollama_server%  q  s    

W%"**c" 	FgWWWE	F 	F 	F 
""eefdg h		
 	

s3   A AA AA A 	A:A55A:c                      	 ddl } | j                  | j                        j                  }t        j
                  dk(  rt        |      dz  S t        |      dz  S # t        $ r Y yw xY w)zj
    Get process RSS memory in MB.
    On Linux, ru_maxrss is in KB. On macOS, ru_maxrss is in bytes.
    r   Ndarwini   i   )resource	getrusageRUSAGE_SELF	ru_maxrsssysplatformr  rp  )r(  r+  s     rg   _get_process_rss_mbr.    sd    
&&x';';<FF	<<8##{33Y$&& s   A	A A 	A&%A&c                  $    t               } | y| dS )Nunknown.2f)r.  )rss_mbs    rg   _rss_mb_for_logr3    s     "F~S\ri   
model_listdetailsmax_concurrencyinstrumentation_contextc                    K   	 t        | |||       d {   S 7 # t        $ r/}dt        |      vr t        | ||       d {  7  cY d }~S d }~ww xY ww)N)r4  r5  r6  r7  r7  r4  r5  r6  )r   r  r  )r4  r5  r6  r7  r  s        rg   -_run_direct_health_check_with_instrumentationr:    sp     
)!+$;	
 
 	
 
  	
$CF2 *!+
 
 
 	
	
sH   A  A 	AAAA
AAAAhealthy_endpointsunhealthy_endpointsc           
          | yddl }ddlm} ||j                  nd}|j                         }t	        j
                   || |||||             y)zKFire-and-forget: persist health check results to DB if prisma is available.Nr   )$_save_background_health_checks_to_dbbackground_health_check)
checked_by)r  0litellm.proxy.health_endpoints._health_endpointsr>  pod_idr  r  )	r]  shared_health_managerr4  r;  r<  time_moduler>  r@  r  s	            rg   )_schedule_background_health_check_db_saverE    sh      !, 	$$& 
 !!#J,!	
	ri   c           	         ddl m} 	 t        t        j                  sy || |      }|rst        j                  j                  |       t        j                  dt        d |j                         D              t        d |j                         D                     yy# t        $ r)}t        j                  dt        |             Y d}~yd}~ww xY w)	z
    Write deployment health states to the router's health state cache
    for health-check-driven routing. No-op if the feature is disabled.
    r   )build_deployment_health_statesN)r;  r<  z:health_check_routing_state_updated healthy=%d unhealthy=%dc              3   D   K   | ]  }|j                  d       sd  yw
is_healthyr  Nr  .0ss     rg   	<genexpr>z6_write_health_state_to_router_cache.<locals>.<genexpr>  s     F!!%%2EAF     c              3   D   K   | ]  }|j                  d       rd  ywrI  rK  rL  s     rg   rO  z6_write_health_state_to_router_cache.<locals>.<genexpr>  s     J!aeeL6IAJrP  z0Failed to write health state to router cache: %s)litellm.proxy.health_checkrG  r  enable_health_check_routinghealth_state_cacheset_deployment_health_statesr}   re  sumvaluesrp  r|  r  )r;  r<  rG  statesr  s        rg   #_write_health_state_to_router_cacherY    s     J
Z%K%K// 3
 ))FFvN &&LFv}}FFJv}}JJ   
$$>A	
 	

s   B A>B 	C(CCc                  F  K   t         t        t         t              r	t         dk  ryt        r$t	        j
                  dt         t        t               dat	        j                  dt         t        t        t        t        j                         t                      d} t        r8t        2ddlm}  |t        t         t"              } t	        j                  d       	 t$        d	z  ad
t$         }t'        j(                         }t+        j,                  t.              xs g }t1        |      }|D cg c]&  }|j3                  di       j3                  dd      s|( }}t1        |      }|}t        t        t              rt        dkD  r|dkD  rt5        |t              }t	        j6                  d|||t         t        || dut        j                         t               
       dd|d}	t        t        nd}
| %	 | j9                  ||
t               d{   \  }}n!tA        |t        t        |	       d{   \  }}|tB        d<   |tB        d<   t1        |      tB        d<   t1        |      tB        d<   t'        j(                         |z
  dz  }t	        j6                  d||t1        |      t1        |      |t         t        j                         t               	       |t         dz  kD  rt	        j
                  d||t                tE        tF        | |||       tI        ||       tK        jL                  t                d{    cc c}w 7 6# t:        $ rL}t	        j<                  dt?        |             tA        |t        t        |	       d{  7  \  }}Y d}~_d}~ww xY w7 o7 iw)z
    Periodically run health checks in the background on the endpoints.

    Update health_check_results, based on this.
    Uses shared health check state when Redis is available to coordinate across pods.
    Nr   zxbackground_health_check_loop_overlap_detected existing_loop_active=true interval_seconds=%s max_concurrency=%s shared=%sTzzbackground_health_check_loop_started interval_seconds=%s max_concurrency=%s shared=%s details=%s thread_count=%d rss_mb=%s)SharedHealthCheckManager)r  health_check_ttllock_ttlz'Initialized shared health check managerr  zbg-
model_infodisable_background_health_checkFzbackground_health_check_cycle_start cycle_id=%s model_count_total=%d model_count_enabled=%d interval_seconds=%s max_concurrency=%s expected_peak_in_flight=%d shared=%s thread_count=%d rss_mb=%sproxy_background_loop)enabledr  cycle_idr9  zEError in shared health check, falling back to direct health check: %sr;  r<  healthy_countunhealthy_counti  zbackground_health_check_cycle_complete cycle_id=%s model_count_enabled=%d healthy_count=%d unhealthy_count=%d duration_ms=%.2f interval_seconds=%s thread_count=%d rss_mb=%szibackground_health_check_cycle_duration_exceeded_interval cycle_id=%s duration_ms=%.2f interval_seconds=%s)'r[  r  r(  #background_health_check_loop_activer}   r|  r\  rZ  rd  health_check_details	threadingactive_countr3  r  <litellm.proxy.health_check_utils.shared_health_check_managerr[  r    r   !background_health_check_cycle_seqr  	monotoniccopydeepcopyr  lenr  minre  perform_shared_health_checkrp  r  r  r:  r  rE  r]  rY  r  r  )rC  r[  rb  cycle_start_time_llm_model_listmodel_count_totalmmodel_count_enabledexpected_peak_in_flightr7  details_boolr;  r<  r  cycle_duration_mss                  rg   r  r    s     	%/5 A%*$$ G!$#		
 +/' 	E   !#4#@	
 !9)<9!

 	!!"KL
)Q.):;<>>+ --7=20
 %
55r*../PRWX 
 

 "/2"5/5(1,#a'&)*=?W&X#"" P!$#!-""$	
 - #
 %9$D $ 	 !, 0KK.($< L  %'0 D$('	 !# 5F016I23034E0F_-256I2J./!^^-0@@DH"" {!"#$!""$
	
  5 <= (({!%	 	2!	
 	,,=?RSmm1222s 
X
  $**[F H#(,+	  %'$X 	3sz   D)N!++L<BN!0M MM N!-N.DN!5N6N!M 	N8NNNN!NN!N!c                       e Zd Zy)StreamingCallbackErrorN)r^   r  r  r^  ri   rg   rz  rz  	  s    ri   rz  c            
          e Zd ZU dZdpdZdedefdZdedefdZ		 dqde
e   defd	Zd
ededefdZdefdZdefd
edededefdZdedee   defdZdefdZdefdZd Zdqde
e   defdZd
efdZd Zd
edee   fdZd
ede
ee      fdZh dZee   e d <   d
efd!Z!d"e
e"jF                     defd#Z$d
efd$Z%d
e
e   d%e
d&   d'e
d(   fd)Z&d*efd+Z'	 dqd,e
e   de
e   fd-Z(drde)fd.Z*d/e+defd0Z,d/e+defd1Z-d2e+de+fd3Z.d2e
e/   d4e0fd5Z1d6ed7ee2d8      d9e+ddfd:Z3d;eddfd<Z4	 dqd=ed>e
e   defd?Z5	 drd=ed@edefdAZ6dBedefdCZ7e8dDe9de
e   fdE       Z:	 dqdFe
dG   d%e
e;   d4e
dH   de
e   fdIZ<d;ed'e
e#   d%e
e;   ddfdJZ=d;ed*ed4e0ddfdKZ>dL Z?dMe
e/   fdNZ@dOedPe2dQ   dRe9defdSZAd%e;d
edTe
e   fdUZBdVeCeeDf   defdWZEd%e;de+fdXZFd%e;d4e0fdYZGd%e;fdZZHd%e;fd[ZId%e;fd\ZJd%e;fd]ZKd%e;fd^ZLd%e;fd_ZMd` ZNd%e;fdaZOd%e;fdbZPd%e;fdcZQd%e;fddZRd%e;fdeZSd%e;fdfZTdg ZUd%e;fdhZVd%e;fdiZWdj ZXdkeCeeYf   defdlZZdmee   fdnZ[d%e;fdoZ\y)sProxyConfigz}
    Abstraction class on top of config loading/updating logic. Gives us one place to control all config updating logic.
    r.  Nc                 <    i | _         d | _        d | _        g | _        y rP  )config_last_semantic_filter_config_last_hashicorp_vault_configworker_registry)selfs    rg   __init__zProxyConfig.__init__	  s!    &(FJ)FJ)<>ri   r  c                     t         j                  j                  |      syt         j                  j                  |      \  }}|j	                         dk(  xs |j	                         dk(  S )NFz.yamlz.yml)r  rX   r  re  lower)r  r  r  file_extensions       rg   r  zProxyConfig.is_yaml	  sW    ww~~./GG,,-=>>##%0TN4H4H4Jf4TTri   rj  c           	          	 t        |d      5 }t        j                  |      xs i cddd       S # 1 sw Y   yxY w# t        $ r}t        d| dt	        |             d}~ww xY w)z,
        Load and parse a YAML file
        rT  NzError loading yaml file r\   )r   yaml	safe_loadrp  r  )r  rj  rd   r  s       rg   _load_yaml_filezProxyConfig._load_yaml_file	  sh    	Ni% 2~~d+1r2 2 2 	N6ykCF8LMM	Ns)   = 1	= := = 	A%A  A%c           	        K   |xs t         }||a t        j                  j                  |       r,t	        | d      5 }t        j                  |      }ddd       n|t        d|       g i i i d}t        d      | j                  |t        j                  j                  t        j                  j                  |xs d                  }|S # 1 sw Y   ixY ww)z
        Given a config file path, load the config from the file.
        Args:
            config_file_path (str): path to the config file
        Returns:
            dict: config
        NrT  zConfig file not found: )r4  r  router_settingsr  zConfig cannot be None or Empty.r  )r~  base_dir)rR  r  rX   r9  r   r  r  rp  _process_includesdirnameabspath)r  r  rj  config_filer~  s        rg   _get_config_from_filez!ProxyConfig._get_config_from_file	  s      %=(=	'$4! 77>>YK)c* 5k45 5"5i[ABB !$&#%$&	F >=>>''BGGOOBGGOOIOQS4T$U ( 

 )5 5s   <C CB C CC r~  r  c                    d|vr|S t        |d   t              st        d      |d   D ]  }t        j                  j                  ||      }t        j                  j                  |      st        d|       | j                  |      }|j                         D ]3  \  }}t        |t              r||v r||   j                  |       /|||<   5  |d= |S )au  
        Process includes by appending their contents to the main config

        Handles nested config.yamls with `include` section

        Example config: This will get the contents from files in `include` and append it
        ```yaml
        include:
            - model_config.yaml

        litellm_settings:
            callbacks: ["prometheus"]
        ```
        includez&'include' must be a list of file pathszIncluded file not found: )r  r  r  r  rX   r:  r9  r3  r  itemsextend)r  r~  r  include_filerj  included_configr  r  s           rg   r  zProxyConfig._process_includes	  s     F"M&+T2EFF #9- 	(LX|<I77>>),'*CI;(OPP"229=O-335 (
UeT*sf}3K&&u-"'F3K	(	( 9ri   
new_configc                   K   	 t         t        j                  dd      du st        rv|j	                         }d|v r0|d   r+| j                  |d   d      }| j                  |      |d<   |j                  dd        t         j                  |d	       d {    y t        t         d
      5 }t        j                  ||d       d d d        y 7 8# 1 sw Y   y xY ww)Nr  FTenvironment_variables)r  return_original_valuer  r4  r~  )data
table_namerV  )default_flow_style)r]  r  r  r  rl  !_decrypt_and_set_db_env_variables_encrypt_env_variablespopinsert_datar   rR  r  dump)r  r  config_to_savedecrypted_env_varsr  s        rg   save_configzProxyConfig.save_config
  s    	
 $  !4e<D 
 (__.N (>9"#:; &*%K%K*89P*Q*. &L &" ;?:U:U*< ;V ;67 |T2++H+UUU ./#6 M+		*keLM M	 VM Ms*   BCCC/C
CCCr   depth	max_depthc                    ||kD  rt        j                  d| d       |S |j                         D ]  \  }}t        |t              r| j                  ||dz   |      ||<   1t        |t              r0|D ]*  }t        |t              s| j                  ||dz   |      }, qt        |t              s|j                  d      st        |      ||<    |S )a  
        Check for os.environ/ variables in the config and replace them with the actual values.
        Includes a depth limit to prevent infinite recursion.

        Args:
            config (dict): The configuration dictionary to process.
            depth (int): Current recursion depth.
            max_depth (int): Maximum allowed recursion depth.

        Returns:
            dict: Processed configuration dictionary.
        zMaximum recursion depth (z") reached while processing config.r  )r~  r  r  os.environ/)
r}   r|  r  r  r  _check_for_os_environ_varsr  r  r@  r  )r  r~  r  r  r  r  items          rg   r  z&ProxyConfig._check_for_os_environ_vars8
  s     9 ((+I;6XY M ,,. 	0JC%&"== 	Y > s E4(! D!$-#>>#'uqyI  ?   E3'E,<,<],K(/s	0 ri   r  all_teams_configc                    i }|D ]3  }d|vr!t        dt        j                  |             ||d   k(  s1|} n |j                         D ]6  \  }}t	        |t
              s|j                  d      s)t        |      ||<   8 |S )Nr  zteam_id missing from team: r  )rp  SENSITIVE_DATA_MASKER	mask_dictr  r  r  r@  r  )r  r  r  team_configteamkvs          rg   _get_team_configzProxyConfig._get_team_config]
  s    $ 	D$12G2Q2QRV2W1XY  $y/)"	  %%' 	/DAq!S!all=&A!+AA	/ ri   c                     | j                         }|j                  di       }|j                  dd      }|i S | j                  ||      }|S )z^
        - for a given team id
        - return the relevant completion() call params
        r  default_team_settingsN)r  r  )r  r  r  )r  r  r~  r  r  r  s         rg   load_team_configzProxyConfig.load_team_configl
  sh     &&( "::&8"=+//0GN#I++.> , 
 ri   cache_paramsc                 L   ddl m} d|v r|d   t         _        d|v r|d   t         _         |di |t         _        t         j                  Yt        t         j                  j                  t        t        f      r*t         j                  j                  at        t        _
        y y y )Nr   Cacher  default_redis_ttlr^  )rg  r  r  r  rh  r  r   r   r  r  r  )r  r  r  s      rg   _init_cachezProxyConfig._init_cache
  s    
 	""l2,89P,QG),.(45H(IG%--==$MM*.?!@*
 !( 3 3.?+*
$ri   c                     ddl }t        A|j                  4t        j                  dur!dt        _        t	        j
                  d       yyyy)z
        Enable caching on the router by setting cache_responses=True.
        This ensures caching works without needing caching=True in request body.
        Router passes caching=self.cache_responses to litellm.completion()
        r   NTz8Set router.cache_responses=True after initializing cache)rg  r  rh  cache_responsesr}   re  )r  rg  s     rg   switch_on_llm_response_cachingz*ProxyConfig.switch_on_llm_response_caching
  sO     	 ")**$6)-J& &&J 7 * #ri   c                   K   t         j                  j                  d      t         j                  j                  d      }t         j                  j                  d      }t         j                  j                  d      }t        j                  d||       |dk(  rt        ||       d{   }nt        ||      }|%t        d      | j                  |	       d{   }t        ,t        d
u r$| j                  |t        t               d{   }t        j                  |      }|j                  dd       | j                  |      }| j!                  |       |S 7 7 7 Uw)a  
        Load config file
        Supports reading from:
        - .yaml file paths
        - LiteLLM connected DB
        - GCS
        - S3

        Args:
            config_file_path (str): path to the config file
        Returns:
            dict: config

        r  N LITELLM_CONFIG_BUCKET_OBJECT_KEYLITELLM_CONFIG_BUCKET_TYPEzbucket_name: %s, object_key: %sgcs)bucket_name
object_keyz(Unable to load config from given source.r  T)r~  r]  r  r  r~  )r  r  r  r}   re  r   r   rp  r  r]  r  _update_config_from_dbrl  rm  r  r  update_config_state)r  r  r  r  bucket_typer~  printed_yamls          rg   
get_configzProxyConfig.get_config
  sT    $ ::>>67C**..)EFK(JKJ**..)EFK &&1;
 e#@ +
   3 +
 ~ JKK  55GW5XXF $):d)B66+"3 7  F }}V,0$7000?   /? Ys7   B)E*+E$,4E* E&!1E*E(AE*&E*(E*c                     || _         y rP  r  )r  r~  s     rg   r  zProxyConfig.update_config_state
  s	    ri   c                     	 t        j                  | j                        S # t        $ r;}t	        j
                  dj                  | j                  |             i cY d}~S d}~ww xY w)z
        Returns a deep copy of the config,

        Do this, to avoid mutating the config state outside of allowed methods
        z^ProxyConfig:get_config_state(): Error returning copy of config state. self.config={}
Error: {}N)rl  rm  r~  rp  r}   re  ru   )r  r  s     rg   r  zProxyConfig.get_config_state
  sV    	==-- 	 &&qxxKK
 I	s   ! 	A%0A A% A%c                 j    |j                  d      }g }|r|D cg c]  }t        di | }}|S c c}w )z<
        Load the credential list from the database
        credential_listr^  )r  r  )r  r~  credential_list_dictr  creds        rg   load_credential_listz ProxyConfig.load_credential_list
  sC      &zz*;<BVW$~55WOW Xs   0c           
         |j                  dd      }|s&|j                  di       }|r|j                  dd      }|syg }t        d       |D ]  }|j                  dd      }|j                  di       j                  dd      }t        d	| d
| d       |j                  di       }|rb|j                         D ]J  \  }	}
t        |
t              s|
j                  d      s)|
j                  dd      }t        |      }
|
||	<   L ||d<   	 t        di |}|j                  |        |r|S dS # t        $ r/}t        j                  d| dt	        |              Y d}~d}~ww xY w)a/  
        Parse and validate search tools from config.
        Loads environment variables and casts to SearchToolTypedDict.

        Args:
            config: Config dictionary containing search_tools

        Returns:
            List of validated SearchToolTypedDict or None if not configured
        search_toolsNr  z6[32mLiteLLM: Proxy initialized with Search Tools:[0msearch_tool_namer  litellm_paramssearch_provider	[32m    z (z)[0mr  zError parsing search tool r\   r^  )r  rt   r  r  r  r@  r	  r  r  r  rp  r}   r  )r  r~  search_tools_rawr  search_tools_parsedsearch_toolr  r  r  r  r  _vsearch_tool_typedr  s                 rg   parse_search_toolszProxyConfig.parse_search_tools  s    "::nd;%zz*<bA#3#7#7#M 9;J	
 , 	K*/A2F)oo.>CGG!2O L!1 2"_4EXNO )__-=rBN*002 .DAq!!S)all=.IYY}b9&rN,-q)	.
 1?,-9L9[{9[!#**+<=+	8 ':"CtC  $**01A0B"SVHM 	s   D11	E):$E$$E)>   HOMEPATHUSERSHELLLOGNAMENO_PROXYno_proxy
LD_PRELOAD
PYTHONHOME
PYTHONPATHPYTHONSTARTUPLD_LIBRARY_PATHDYLD_LIBRARY_PATHDYLD_INSERT_LIBRARIES_BLOCKED_ENV_KEYSc                    |j                  dd       }|r|j                         D ]  \  }}|| j                  v rt        j                  d|       +t        |t              r4|j                  d      r#t        |      }|[|t        j                  |<   ot        |      t        j                  |<    d|v r3t        j                  dd       t        _        t        j                         ay )Nr  z-Skipping blocked environment variable key: %sr  )secret_nameLITELLM_LICENSE)r  r  r  r}   r|  r  r  r@  r  r  r  r  r  license_strr  rB  )r  r~  r  r  r  resolved_secret_strings         rg   _load_environment_variablesz'ProxyConfig._load_environment_variablesN  s     !'

+BD I 399; 1
U$000(00G  eS)e.>.>}.M<J$)=* .9*@

3 '*%jBJJsO71< !$99-/YY7H$-O*-88:ri   r   c                 "  K   | j                  |       d{   }| j                  |       |j                  di       }|r|t        _        |j                  dd      }|i }|rd}d}|j                         D ]  \  }}	|dk(  r|	d	u rt        | d
       ddlm}
 i }d|v r|d   }|j                  |       |j                  dd      }t        j                  d|       |dk(  s|dk(  rt        |j                               dk(  rt        dd      }t        dd      }d}|j                  |||d       t        dd      t        dd      }|j                  d|i       t        j                  d|||       t        j                  d|||       t        j                  d|||       t        j                  d|||       |j                         D ]6  \  }}	t        |	t               s|	j#                  d      s)t        |	      ||<   8 | j%                  |       t        j&                  t        j                  | d|        |dk(  r|	du r|dk(  r t)        |	t*        ||       }|t        _        |d!k(  r*dd"lm}  ||	       t        j2                  | d#|        2|d$k(  r*dd%lm}  ||	       t        j2                  | d&|        a|d'k(  r*dd(lm}  ||	       t        j2                  | d)|        |d*k(  rdd+lm}  |di |	t        _         |d,k(  rtC        |	t*        ||-       |d.k(  rdd/l"m#}  |di |	t        _$        |d0k(  r?tK        |	|1      gt        _&        t        j                  d2t        jL                          *|d3k(  rtO        |	      t        _(        E|d4k(  rAtO        |	      t        _)        t        jP                  pt        jR                  t        _(        |d5k(  r<dd6l*m+} |	D cg c]  }|d7   tK        |d8   |1      d9 c}t        _,         |        |d:k(  rg t        _-        |	D ]  }d;|v r*t        j\                  j_                  tK        |<             1t        j\                  j_                  |       d=|v sUdd>l0m1} |^t        j                  d?       |je                           t        | d@t        jZ                   dA|        |dBk(  rg t        _3        |	D ]O  }d;|v r*t        j\                  ji                  tK        |<             1t        j\                  ji                  |       Q t        | dCt        jf                   dA|        |dDk(  rg t        _5        |	D ]O  }d;|v r*t        jj                  jm                  tK        |<             1t        jj                  jm                  |       Q |j                  dEt        jn                        }|r#t        | dFt        jj                   dA|        t        jp                  dG       |dk(  r|dHk(  rx|	j                  dIi       }|j                  dJd      a9|j                  dKg       a:|j                  dLdM      a;t        j                  | dNtr         dOtt         dPtv         |        Q|dQk(  rQty        |	      D ]  \  }}	 t{        di |  t        j                  | dT| dU|	 |        t        t        ||	       |dVk(  r|	ot        |	t~              r_|	j                         D ]6  \  }} t        | t               s| j#                  d      s)t        |       |	|<   8 t        di |	t        _C        t}        dW|	       |dXk(  r?|	d	u r;d	t        _D        t        j                          t        j                  | dY|        ot        j                  | dT| dU|	 |        t        t        ||	        |j                  dZi       }!|!i }!d}"d}#|!r|!j                  d[d      }$|$t        di |$t        _G        |!j                  d\d      }%| j                  |%|]       |!j                  d^d      }&t        |&_       |!j                  d`d      }'t        |'a       | j                  |!b       |!j                  dcd      }(|(rG|(j#                  d      r6t        j                  dd       t        |(      }(t        j                  de|(       |!j                  dft        dgd            aLt        r$t        j#                  d      rt        t              aLt        $t        t        t               rt        t              aNnt        j                  dh       |!j                  did      })|) t        j                  tO        |)      dj       t        j                  dkdl      j                         dmk(  }*|*r#t        t        sd	aVt        jp                  dn       |!j                  do      }+|+r#t        t        sd	aWt        jp                  dp       |!j                  dqd      aXt        daXt        |!dq<   |!j                  drd      },|,tK        |,|1      aY|!j                  dsd      }-|-tK        |-|1      aZ|!j                  dtd      }.|.tK        |.|1      a[|!j                  dud      }/|/tK        |/|1      a\t        t        j                  |!       d{    |!j                  dvd      |!dv   a_t        |!dv   w       d{    |!j                  dxdy      aa|!j                  dzd      }0|0t*        du rt        d{      |!j                  d|t              ac|!j                  d}t              ad|!j                  d~t              ae|!j                  dt              af|!j                  dt              ag|!j                  dd      ah|!j                  dd      ai|!j                  dt              ak|!j                  dd      al|!j                  dd	      am|!j                  dd      }"|!j                  dd      }#t        j2                  dt        t        t        t        t        |"       |!j                  dd      }1|1|1D 2cg c]  }2t        di |2 c}2|!d<   |!j                  d      .t*        d	ur&t        dt        j                  j                  z         d|!v r"|!d   t        _s        t        j                         adt        j&                  dui}3|"rd	|3d<   |#|#|3d<   |j                  dd      }4|4r|4|3d<   t        d       |4D ]  }5|5d   j                         D ]9  \  }6}7t        |7t               s|7j#                  d      s)t        |7      |5d   |6<   ; t        d|5j                  dd       d       |5d   d   }8|5d   j                  dd      }9d|8v s|9t                 d}:|j                  dd      };|;rx|;d   j                         D ]W  \  }6}7t        |7t               s|7j#                  d      s)|7j                  dd      } t        j                  |       }7|7|;d   |6<   Y t        di |;}:| j                  |      }<|j                  dd      }=t        |=       |j                  dd      }>t        |>       |j                  dd      }?t        j                  |?       |j                  dd      }@|@rt        @t~              rddh}At        j                  j                         D Bcg c]	  }B|BAvsB }C}B@j                         D ];  \  }6}7|6Cv r|7|3|6<   |6dv rt        d|6 d      t        jp                  d|6 d       = t        j                  di |3|:|<t        d	      d	d}t        .|j&                  j                   |j                  t               d}D||j                  dd      }DDrt        D||       | j                  |t        |       d{    d}E||j                  dd      }EErddlm}F  |FE|       | j                  |      }G|Gt        _        | j                  |       d{    ||j                         |!fS 7 c c}w # t|        $ rJ t        |t~              rt}        dR| dS|j                                t}        dR| dSt        |             w xY w7 )7 c c}2w c c}Bw 7 7 w)z<
        Load config values into proxy global state
        r  Nr  callback_settingsr  z[94mz[0mrh  Tz
Setting Cache on Proxyr   r  r  rV   rediszpassed cache type=%szredis-semantic
REDIS_HOST
REDIS_PORT)rV   hostportREDIS_PASSWORDpasswordz%sCache Type:%s %sz%sCache Host:%s %sz%sCache Port:%s %sz%sCache Password:%s %sr  )r  zSet Cache on LiteLLM ProxyF
guardrails)guardrails_configrB  r  r  global_prompt_directory)set_global_prompt_directoryz,Set Global Prompt Directory on LiteLLM Proxyglobal_bitbucket_config)set_global_bitbucket_configz,Set Global BitBucket Config on LiteLLM Proxyglobal_gitlab_config)set_global_gitlab_configz)Set Global Gitlab Config on LiteLLM Proxypriority_reservation_settings)PriorityReservationSettings	callbacks)r  rB  r  r  model_group_settings)ModelGroupSettingspost_call_rules)r  r  zlitellm.post_call_rules: max_internal_user_budget default_max_internal_user_budgetcustom_provider_map)custom_llm_setupprovidercustom_handler)r  r  rl  r_  r  
prometheusPrometheusLoggerzmounting metrics endpointz! Initialized Success Callbacks - rp   failure_callbackz! Initialized Failure Callbacks - audit_log_callbacksstore_audit_logsz# Initialized Audit Log Callbacks - z'audit_log_callbacks' is configured but 'store_audit_logs' is not enabled. Audit log callbacks will not fire until 'store_audit_logs: true' is added to litellm_settings.r  background_modepolling_via_cacher  r  r  z( Initialized polling via cache: enabled=z, native_background_mode=z, ttl=r  z4team_id missing from default_team_settings at index=z
passed in value=z setting litellm.=upperbound_key_generate_paramsz=Invalid value set for upperbound_key_generate_params - value=	json_logsz  Enabled JSON logging via configr  key_management_settingskey_management_system)r"  r  use_google_kmsr#  r  r  )r  r  zGOING INTO LITELLM.GET_SECRET!zRETRIEVED DB URL: %srQ  r  zLITELLM_MASTER_KEY is not set! All requests will be treated as INTERNAL_USER with no admin access. Set LITELLM_MASTER_KEY for production use.user_api_key_cache_ttl)r  r  GENERIC_CLIENT_USE_PKCEfalserR  u  GENERIC_CLIENT_USE_PKCE=true but Redis is not configured for LiteLLM caching. PKCE verifiers will not be shared across instances — callbacks may land on a different pod than the login request and fail silently. Configure Redis via the 'cache' section in your proxy config, or enable sticky sessions for single-instance deployments. Set PKCE_STRICT_CACHE_MISS=true to fail fast with a 401 on cache misses instead of continuing without a code_verifier.control_plane_urlu\  control_plane_url is configured but Redis is not configured for LiteLLM caching. Login codes (SSO and /v3/login) will not be shared across instances — the /v3/login/exchange call may land on a different pod and fail with 401. Configure Redis via the 'cache' section in your proxy config, or ensure sticky sessions for single-instance deployments.r  custom_authcustom_key_generate
custom_ssocustom_ui_sso_sign_in_handlerpass_through_endpointsr.  r  r  allowed_ipsz\allowed_ips is an Enterprise Feature. Please add a valid LITELLM_LICENSE to your envionment.r  r  proxy_batch_polling_intervalr  disable_spend_logsbackground_health_checksrZ  r[  r\  rf  rS   health_check_staleness_thresholdz}background_health_check_config enabled=%s shared=%s interval_seconds=%s max_concurrency=%s details=%s health_check_routing=%srole_permissionsenforced_paramszTrying to use `enforced_params`litellm_licenser  r4  z<[32mLiteLLM: Proxy initialized with Config, Set models:[0mr  r  
model_namer  modelapi_baser  assistant_settingsfinetune_settingsfiles_settingsdefault_vertex_configr  r  >   r[  r\  'zQ' is NOT a valid router_settings parameter. Please move it to 'general_settings'.zKey 'zC' is not a valid argument for Router.__init__(). Ignoring this key.async_only_mode)assistants_configr  router_general_settingsignore_invalid_deployments)rh  )all_guardrailsr  r  )r~  r]  r  prompts)init_prompts)all_promptsr  r^  )r  r  r  rg  r  r  rt   litellm.caching.cachingr  updater}   re  rn  r  r  r  r  r@  r  rh  r   rB  guardrail_name_config_maplitellm.integrations.dotpromptr  rd  litellm.integrations.bitbucketr  litellm.integrations.gitlabr  litellm.types.utilsr
  r	  r   litellm.types.routerr  r  r   r  r  r  r  rm  r  r  rl  r  add_litellm_success_callbacklitellm.integrations.prometheusr  _mount_metrics_endpointr  add_litellm_failure_callbackr  r  r  r|  r  r  r  	enumeraterC   rp  r  rV   setattrr  r  r   _turn_on_jsonr  _key_management_settingsinitialize_secret_managerr  r  _load_alerting_settingsrQ  r   litellm_master_key_hashcriticalr  update_cache_ttlr  r  r  r  r  r  r  rT  rV  rW  rX  rA  load_enterprise_configr  r   r  r  r  r  r1  r  r2  rY  rZ  r   r[  r\  rf  r@   r*   not_premium_userr  r  r  r  r%  r	  r   r  r   r   r   set_default_vertex_configr{   get_valid_argsr  r  _update_redis_cacher   _init_policy_enginer]  "litellm.proxy.prompts.init_promptsrG  r  r  _init_non_llm_configsget_model_list)Hr  r   r  r~  r  r  blue_color_codereset_color_coder  r  r  r  cache_params_in_config
cache_type
cache_host
cache_portcache_passwordrK  r  r  r  r
  r  r  r  callbackr  _store_audit_logsr  idxteam_setting_kr  r  _enable_hc_routing_hc_stalenessr!  r"  r#  r  r  r&  use_pkcecp_urlr*  r+  r,  r-  r0  rbac_role_permissionsrole_permissionrouter_paramsr4  r9  r  r  litellm_model_namelitellm_model_api_baserB  r;  r  finetuning_configfiles_configr>  r  exclude_argsxavailable_argsguardrails_v2rF  rG  r  sH                                                                           rg   r  zProxyConfig.load_configv  s     "__>N_OO(((7 #JJ':B?(9G% "::&8$?#!(O(.446 _1
U'>etm_--EFG=#%L%)991A.1Q.$++,BC!-!1!1&'!BJ(../EzR #g-?O1Ol//12a7%/d%C
%/d%C
)-$++(2(2(2 &&6=I-78H$-ON(//$.!" -220+,&	 -220+,&	 -220+,&	 -224+,*	 '3&8&8&: B
U%eS1e6F6F}6U0:50AL-B
 $$,$?}}0,22.//IJZI[\ G^L(0E*/%1)9)9	1- 9RG555 06(--*++WXhWij 55 06(--*++WXhWij 22T,U3(--*++TUeTfg ;;O<W ==G9 K'1#%1)9)9	 22G3E3N3NG0--'eFVW/G+ )..3G4K4K3LM 667<U|G4>>?DU|G<77?#DD  8 11> %*	3 ! )-Z(8.=&*+;&<1A/	3G/ %&../1G, %* O(?#<<YY /h ?
 $<<YY (  ,x7!" $4#?$8$>$>(C%& %5$L$L$N)O* *++LWMeMeLffghxgyz ../1G, %* 
(?#<<YY /h ?
 $<<YY (
 *++LWMeMeLffghxgyz 1124G/$) I(?#77>> /h ? $77>>xHI )9(<(<*G,D,D)% ).//RSZSnSnRoop  rB  qC  D -44} N* K' ',ii0A2&FO0?0C0C+U1- .=-@-@0".* )8(;(;E4(H%(..*++STmSn  oH  I_  H`  `f  gx  fy  zJ  yK  L 33-6. )\	/?,?	 )..*++<SE5'JZI[\ GS%0<<(Zt-D&+kkm ;FB)"c2r}}]7S,6rNb	; @H%H  > ([\a[bc  K'ETM(,G%))+(..*++KL\K]^ )..*++<SE5'JZI[\ GS%0_1D	 "::&8"=#!"&6&:&:)4'# '23H 4-40
 %5$8$89PRV$W!**&;!1 + 
 .112BEJN>:"2"6"67Le"T%:MN((:J(K+//EL 7 7 F$**+KL),7$**+A<P)--j)=tDJ j33MB'
3
%*Z*E*4Z*@'$-- d &6%9%9($&" &1"33*/0F*G&* 4  yy!:GDJJLPVVH-55592(00I &))*=>F+33370(00U !1 4 45H% P ($)!4E01 +..}dCK&#2%8H$  #3"6"67Ld"S".+:-@P,( *--lDAJ%"1$7G# -=,@,@/-) -85D7%562
 '2-DDEUVVV  ##$<dCO/?,0, 8+;<T+U  
 .11 %N +..}dCK&<5+@ r  1A0D0D35V1- 1A0D0D35V1- ,<+?+?.0L,( $4#7#7&(<$  "2!5!5$&8"
 ,<+?+?*E,( '7&:&:)5'# %5$8$8')F%! (8';';*D($ $4#7#78NPT#U !1!5!5-u" -002DM !%% P,'%($" %5$8$89KT$R!$0 ,A8' );?;8 !34 !$$%67C , 5'88>>?  !$44-=>O-P*-88: w}} 

 ;?M78$@MM<=ZZd3
*4M,'T $ 	'!"2399; CDAq!!S)all=.I5?]./2C UYY|R%@$AIJ%*+;%<W%E")./?)@)D)DZQU)V&116L6T$&	' <@#ZZ(<dC*+;<BBD @1a%!,,}*E="5B		"A>?&'78;	@
 !4 I6H I =A<S<S=

 #JJ':DA&78 zz"2D9- !'

+BD I#==(	

 !**%6=z/4@ L #>>88:a|>SN  (--/ 
1&'(M!$OO$A3op  )00s"ef
  

/%$9 $% (,
 (V\\-E-E-M&&->&? /3"JJ|T:M,!1! &&' ' 
 	
 	
 )-jjD1GGW?OP  $888G"6 (((777v,,.0@@@k PJ	3R  ) ),=&/&Z[^Z__qr~  sD  sD  sF  rG  %H'" !" #,"VWZV[[mnrs  oA  nB  !C# J WJ8nR	
( 	8s-  AE-AC;GAE-,AE->2AE-2F7AE-+*AE-AC>2A;AE-.AE-7H+AE-#AD.A1AE- AE-2N>AE-0AE1-AE-AEE4AE-AE%CAE-AE-AAE-+AE-.AAE-:AE-C9AE-	AE$AE$C.AE-BAE)BA AE-C"AE+C#AE-C>AE-DAAEEAE-EAE-EAE-E+AE-c                   K   |j                  dd      }|rt        j                  |       |j                  dd      }|rt        j                  |       |j                  dd      }|rDddlm} |j                  di       }|j                  dd      }|j                  ||       d{    |j                  d	d      }|rEdd
lm	}	 t        j                   |	       t        _        t        j                  j                  |       |j                  dd      }
|
r|
D cg c]  }t        di | c}| _        yg | _        y7 c c}w w)zO
        Initialize non-LLM configs eg. MCP tools, vector stores, etc.
        	mcp_toolsN
agent_listmcp_serversr   global_mcp_server_managerr  mcp_aliasesvector_store_registryVectorStoreRegistryr  r^  )r  r   load_tools_from_configr   load_agents_from_config9litellm.proxy._experimental.mcp_server.mcp_server_managerr  load_servers_from_config+litellm.vector_stores.vector_store_registryr  rg  r  load_vector_stores_from_configr  r  )r  r~  mcp_tools_configagent_configmcp_servers_configr  r  r  vector_store_registry_configr  worker_registry_configr  s               rg   re  z!ProxyConfig._init_non_llm_configs  s@    
 "::k48$;;<LM zz,5!99,G#ZZt<
  &zz*<bA*..}dCK+DD"K  
 (.zz2I4'P$'W,,40C0E- ))HH,
 "(,=t!D!2H$-.#(a($D  $&D 1($s%   B&E(E)A5EE0EEr]  r   r  r{   c                 B  K   ddl m} ddlm} |t	        j
                  d       y|j                  dd      }|st	        j
                  d       y|j                  dd      }t	        j                  d	t        |       d
        |||||dud       d{    y7 w)a  
        Initialize the policy engine from config.

        Args:
            config: The proxy configuration dictionary
            prisma_client: Optional Prisma client for DB validation
            llm_router: Optional LLM router for model validation
        r   )init_policies)PolicyValidatorNz'Policy engine: config is None, skippingpoliciesz.Policy engine: no policies in config, skippingpolicy_attachmentszPolicy engine: found z policies in configT)policies_configpolicy_attachments_configr]  validate_dbfail_on_error)	)litellm.proxy.policy_engine.init_policiesr  ,litellm.proxy.policy_engine.policy_validatorr  r}   re  r  rd  rn  )r  r~  r]  r  r  r  r  r  s           rg   rc  zProxyConfig._init_policy_engineG  s      	LP> &&'PQ **Z6 &&'WX$*JJ/CT$J!!!#C$8#99LM	

 +&?'%T1
 	
 	
s   BBBBr  c                 X   |j                  dd      }t        j                  d|        |y|j                  dd      }t        j                  d|        t        j	                  ||j                  dd      |j                  dd      |j                  dd      |j                  d	d      |j                  d
d      t
               |D ]^  }|dk(  r	|t        j                  v st        |ddd	|j                  d	d      i      }|@t        j                  j                  |       ` y)z.
        Initialize alerting settings
        alertingNz_alerting_callbacks: z=_load_alerting_settings: Calling update_values with alerting=alerting_thresholdr  alert_typesalert_to_webhook_urlalerting_argsalert_type_config)r  r  r  r  r  r  r  slack)logging_integrationinternal_usage_cacher  custom_logger_init_args)r  r}   re  r  update_valuesr  rg  )_known_custom_logger_compatible_callbacksr&   r  r  )r  r  _alerting_callbacks_alerting_value_alert_loggers         rg   rZ  z#ProxyConfig._load_alerting_settingsq  sN   
 /22:tD""%:;K:L#MN& +..z4@""KOK\]	
 	''$/334H#N(,,]DA!1!5!56Ld!S*..E.223FM) 	( 	
 * 	WF  WNNNB,2-1#'+-=-A-A/SW-X1	G *88MMgV!	W" 	ri   r"  c                    |||t         j                  j                  k(  rt        d       y|t         j                  j                  k(  rt        d       y|t         j                  j                  k(  r(ddlm} |j                  dt        j                         y|t         j                  j                  k(  rt        d       y|t         j                  j                  k(  rdd	lm}  |        y|t         j"                  j                  k(  rdd
lm}  |        y|t         j(                  j                  k(  rddlm}  |        y|t         j.                  j                  k(  rddlm}  ||       yt5        d      y)z_
        Initialize the relevant secret manager if `key_management_system` is provided
        NTr%  r$  r   )AWSSecretsManagerV2)use_aws_secret_managerr!  )use_aws_kms)GoogleSecretManager)HashicorpSecretManager)CyberArkSecretManager)load_custom_secret_managerr  z&Invalid Key Management System selected)r  r  r  r  
GOOGLE_KMSr  AWS_SECRET_MANAGER-litellm.secret_managers.aws_secret_manager_v2r  load_aws_secret_managerrg  rX  AWS_KMSr  GOOGLE_SECRET_MANAGER-litellm.secret_managers.google_secret_managerr  HASHICORP_VAULT0litellm.secret_managers.hashicorp_secret_managerr  CYBERARK/litellm.secret_managers.cyberark_secret_managerr  CUSTOM4litellm.secret_managers.custom_secret_manager_loaderr  r  )r  r"  r  r  r  r  r  r  s           rg   rY  z%ProxyConfig.initialize_secret_manager  s>    !,$(;(K(K(Q(QQ)dC&*=*H*H*N*NNt4%&99??@ $;;+/,3,L,L <  '*=*E*E*K*KK.%)<)R)R)X)XX $%&*=*M*M*S*SS '(&*=*F*F*L*LL &'&*=*D*D*J*JJ +<LM !IJJc -ri   c                    t        |dd      }|||j                  d<   d|j                  d<   t        du rht        |dd      |j                  d<   t        |dd      |j                  d<   t        |dd      |j                  d<   t        |d	d      |j                  d	<   |j                  t        |j                  t              rld|j                  vr|j
                  |j                  d<   d|j                  v r |j                  d   d
u r||j                  d<   t        di |j                  }|S t        |j
                  |      }|S )z
        Common logic across add + delete router models
        Parameters:
        - deployment
        - db_model -> flag for differentiating model stored in db vs. config -> used on UI

        Return model info w/ id
        model_idNr{  Tdb_model
created_at
updated_at
created_by
updated_byF)r{  r  r^  )r  r^  rB  r  r  r  RouterModelInfo)r  r9  r  r
  _model_infos        rg   get_model_info_with_idz"ProxyConfig.get_model_info_with_id  sD    %UJ=?%(ET"+/EZ(4-4UL$-OE\*-4UL$-OE\*-4UL$-OE\*-4UL$-OE\*'Ju7G7G,N5+++).  &U---%2B2B:2NRW2W/7  ,)=E,<,<=K  *U^^hOKri   	db_modelsc                 |  K   g }t         t        |      dk(  ry|D ]<  }| j                  |      }|j                  "|j	                  |j                         > 	 | j                  t               d{   }|j                  dd      }|r|D ]  }|d   j                         D ]9  \  }	}
t        |
t              s|
j                  d      s)t        |
      |d   |	<   ; |j                  d	i       j                  d
d      }|t         j!                  |d   |d         }nt        |      }|j	                  |        t         j#                         }d}|D ]%  }||vst         j%                  |      }|!|dz  }' |S 7 # t        $ r)}t        j                  dt        |             Y d}~yd}~ww xY ww)a5  
        (Helper function of add deployment) -> combined to reduce prisma db calls

        - Create all up list of model id's (db + config)
        - Compare all up list to router model id's
        - Remove any that are missing

        Return:
        - int - returns number of deleted deployments
        Nr   r9  r  zlFailed to load config in _delete_deployment: %s. Skipping deployment cleanup to avoid removing valid models.r4  r  r  r^  r{  r8  )model_groupr  r{  r  )r  rn  r  r{  r  r  rR  rp  r}   r|  r  r  r  r  r@  r  _generate_model_idget_model_idsdelete_deployment)r  r  combined_id_listrt  r^  r~  r  r4  r9  r  r  r  router_model_idsdeleted_deployments
is_deleteds                  rg   _delete_deploymentzProxyConfig._delete_deployment  s      Y1!4  	7A4414=J}}( ''
6	7	??<Q?RRF ZZd3
# 2!"2399; CDAq!!S)all=.I5?]./2C
 !99\26::4F#)<<$),$7',-='>  =  H
  #8}H ''1!2$ &335  ( 	-H//'99X9F
)'1,'		-
 #"K S 	 ((NA
 	s`   ;F<F<F 5F6F :AF<=F<BF<"F<;	F<F 	F9F4/F<4F99F<c                    ddl }t        yd}|D ]  }|j                  }t        |t              rH|j                         D ])  \  }}t        |t              st        ||d      }|||<   + t        d
i |}nt        j                  d|        | j                  |d      }	t        j                  t        |j                  ||	            }
|
|d	z  } |S )z
        Iterate through db models

        for any not in router - add them.

        Return - number of deployments added
        r   NTr  r  r  HInvalid model added to proxy db. Invalid litellm params. litellm_params=)r9  r  r8  r  r^  )
deploymentr  r^  )base64r  r  r  r  r  r  r   r   r}   r  r  upsert_deploymentr   r8  )r  r  r  added_modelsrt  _litellm_paramsr  r  _valuer  addeds              rg   _add_deploymentzProxyConfig._add_deployment:  s    	 	"A..O/40+113 4DAq!!S)!5"#$" .4*4 #1"C?"C %**^_n^op 55$ 6 K 00% ||#2* 1 E  !?	"@ ri   
new_modelsc                    g }|D ]  }|j                   }t        |t              r|j                         }t        |t              r7|j                         D ]  \  }}t        ||d      }|||<    t        di |}nt        j                  d|        | j                  |      }|j                  t        |j                  ||      j                  d              |S )NTr  r  r  r  exclude_noner^  )r  r  r   
model_dumpr  r  r   r   r}   r  r  r  r   r8  to_json)	r  r  _model_listrt  r  r  r  decrypted_valuer  s	            rg   decrypt_model_list_from_dbz&ProxyConfig.decrypt_model_list_from_dbk  s     	A..O/95"1"<"<">/40+113 9DAq&:Qd'O *9OA&	9
 #1"C?"C$**^_n^op 55A5>K ||#2* 't','	6 ri   r  c                 ^  K   i }d }	 t         j                          d {   }| j                  |      }	 t        |t              r|ng }t        t        t	        j                  dt        |              | j                  |      }t        |      dkD  s|rt	        j                  d|        t        j                  |t!        d      |d      a	t	        j                  d	t                n`t	        j                  dt        |              |t        |t        _        | j%                  |
       d {    | j'                  |
       t        t        j+                         a| j/                  |       | j1                  |t        t2               d {    | j5                  |t6        |       y 7 # t        $ r*}t	        j
                  dt        |             Y d }~d }~ww xY w7 # t        $ r+}t	        j(                  dt        |              Y d }~d }~ww xY w7 w)NziFailed to load config in _update_llm_router: %s. Proceeding with model loading using cached/empty config.zlen new_models: )r  r   z_model_list: Tr@  )r4  rC  r  rD  zupdated llm_router: )r  z+Error adding/deleting model to llm_router: )config_datar  r]  )r  r  r  )r  r  r  rp  r}   r|  r  r  r  r  rQ  re  rn  r  rg  r{   r  r  r  r  r  rf  r  _add_callbacks_from_db_config#_add_router_settings_from_db_configr]  $_add_general_settings_from_db_configr  )r  r  r  r  r  r  models_listr  s           rg   _update_llm_routerzProxyConfig._update_llm_router  s(     	 , 7 7 99K22;?L"	.8T.J
PRK!j&<$**-=c+>N=O+PQ$($C$C* %D %
 {#a'<(..{m/LM!(#.0E,01 &237"J )..1Ej\/RS$**-=c+>N=O+PQ+
0F.:J+---DDD $${$; !'668N 	**;7 66#
- 7 
 	
 	

 	11#-/ 	2 	
s : 	 ((KA 	B E
  	 **=c!fXF 		
s   H-F< F9F< DG4 :G2;G4 A
H-H+H-9F< <	G/G*$H-*G//H-2G4 4	H(=!H#H-#H((H-rn  event_types)successfailureexisting_callbacksc                 0   |t         j                  v r|D ]  }t        ||        y||vrl|dgk(  r t         j                  j	                  |       y|dgk(  r t         j                  j                  |       yt         j                  j                  |       yy)aQ  
        Helper method to add a single callback to litellm for specified event types.

        Args:
            callback: The callback name to add
            event_types: List of event types (e.g., ["success"], ["failure"], or ["success", "failure"])
            existing_callbacks: The existing callback list to check against
        r  r  N)rg  r  r   r  rQ  rT  r  )r  rn  r  r  
event_types        rg   4_add_callback_from_db_to_in_memory_litellm_callbacksz@ProxyConfig._add_callback_from_db_to_in_memory_litellm_callbacks  s     wHHH) T
=h
ST//yk)00MMhW+00MMhW00EEhO 0ri   r  c                 
   |j                  di       xs i }|j                  dd      }|j                  dd      }|j                  dd      }|:t        |t              r*|D ]%  }| j                  |dgt        j
                         ' |:t        |t              r*|D ]%  }| j                  |dgt        j                         ' |=t        |t              r,|D ]&  }| j                  |ddgt        j                         ( yyy)	z:
        Adds callbacks from DB config to litellm
        r  rl  Nr  r  r  )rn  r  r  r  )r  r  r  r  rg  rl  r  r  )	r  r  r  success_callbacksfailure_callbacksr  rl  r  rn  s	            rg   r  z)ProxyConfig._add_callbacks_from_db_config  s2    '??+=rBHb,001CTJ,001CTJ$((d;	(Z8I4-P$5  II-!*'.'?'? J  (Z8I4-P$5  II-!*'.'?'? J   Z	4%@% II%!*I 6'.'8'8 J  &A ri   r  new_encryption_keyc                 ^    i }|j                         D ]  \  }}t        ||      }|||<    |S )zR
        Encrypts a dictionary of environment variables and returns them.
        )r  r  )r  r   )r  r  r  encrypted_env_varsr  r  encrypted_values          rg   r  z"ProxyConfig._encrypt_env_variables  sK      )//1 	4DAq2,>O %4q!		4
 "!ri   r  c           	          i }|j                         D ].  \  }}	 t        |||      }||t        j                  |<   |||<   0 |S # t        $ r*}t        j                  d|t        |             Y d}~ad}~ww xY w)a!  
        Decrypts a dictionary of environment variables and then sets them in the environment

        Args:
            environment_variables: dict - dictionary of environment variables to decrypt and set
            eg. `{"LANGFUSE_PUBLIC_KEY": "kFiKa1VZukMmD8RB6WXB9F......."}`
        r  Nz#Error setting env variable: %s - %s)r  r   r  r  rp  r}   r  r  )r  r  r  r  r  r  r  r  s           rg   r  z-ProxyConfig._decrypt_and_set_db_env_variables  s      )//1 	DAq
"6:O# #.$3BJJqM,;&q)	 "!	  $**91c!f s   (A	A9 A44A9variables_dictc                 `    i }|j                         D ]  \  }}t        ||d      }|||<    |S )zF
        Decrypts a dictionary of variables and returns them.
        Tr  )r  r   )r  r
  decrypted_variablesr  r  r  s         rg   _decrypt_db_variablesz!ProxyConfig._decrypt_db_variables5  sL     !"((* 	5DAq2QdO &5"		5
 #"ri   r  c                 L   | yd}t        | t              r| }n*t        | t              rddl}	 t	        j
                  |       }t        |t              r|r|S y# t        j                  |j                  f$ r, 	  |j                  |       }n# |j                  $ r Y nw xY wY _w xY w)z
        Parse a router_settings value that may be a dict or a JSON/YAML string.

        Returns a non-empty dict if valid, otherwise None.
        Nr   )	r  r  r  r  r  r  	YAMLErrorJSONDecodeErrorr  )r  parsedr  s      rg   _parse_router_settings_valuez(ProxyConfig._parse_router_settings_valueA  s     =!%eT"Fs#. fd#M NND$8$89 'TZZ.F++ s5   A B#8B
B#BB#BB#"B#user_api_key_dictrF   r   c                   K   | | j                  t        |dd            }||S |T|j                  H	 t        |j                  |t        |       d{   }| j                  t        |dd            }||S 	 yy7 '# t
        $ r Y yw xY ww)u  
        Get router_settings in priority order: Key > Team

        Uses the already-cached key object and the cached team lookup
        (get_team_object) to avoid direct DB queries on the hot path.

        Global router_settings are NOT looked up here — they are already
        applied to the Router object at config-load / DB-sync time.

        Returns:
            dict: router_settings, or None if no settings found
        Nr  )r  r]  r  r  )r  r  r  r   r  rp  )r  r  r]  r  key_settingsteam_objteam_settingss          rg   !_get_hierarchical_router_settingsz-ProxyConfig._get_hierarchical_router_settings]  s     * (<<)+<dCL '##
 (->-F-F-R!0-55"/'9&7	"  !% A AH&7>! !,(( -   	s@   1B A> A<#A> 8B:B<A> >	B
B	B

Bc                   K   |||j                   j                  j                  ddi       d{   }|j                  di       }i }|Ft	        |t
              r6|4t	        |j                  t
              rddlm}  |||j                        }n=|t	        |t
              r|}n(|&t	        |j                  t
              r|j                  }|r |j                  di | yyyy7 w)z
        Adds router settings from DB config to litellm proxy

        1. Get router settings from DB
        2. Get router settings from config
        3. Combine both
        4. Update router settings
        N
param_namer  wherer   )_update_dictionaryr^  )
r  litellm_config
find_firstr  r  r  param_valuerm  r  update_settings)r  r  r  r]  db_router_settingsconfig_router_settingscombined_router_settingsr  s           rg   r  z/ProxyConfig._add_router_settings_from_db_config  s     !m&?'4'7'7'F'F'Q'Q#%67 (R ( " &1__5F%K"')$&25t<&21==tD<+=*,>,J,J,( (3
&9 ,B(#/J"..5 ,>+I+I('*
**F-EF (9 '@!"s   0C*C(B6C*c                    |j                  di       }|>d|v r9||j                  dd      t        |d   t              r|j                  dd      t        |d   t              rt        |d         }t        |d         }t        |j	                  |            }t        |d         |d   D cg c]  }||d   vr| c}z   }t        j                  d|d    d|d    d|        ||d<   |j                  |d          nO| i }|d   |d<   |j                  |d          n-t        |t              r|d   |d<   |j                  |d          |:d|v r6|d   |d<   |d   |_	        |j                  j                  |d   t        	       |2d
|v r-|d
   |d
<   |j                  j                  |d
   t               yyyc c}w )z
        Adds general settings from DB config to litellm proxy

        Args:
            config_data: dict
            general_settings: dict - global general_settings currently in use
            proxy_logging_obj: ProxyLogging
        r  Nr  zMerging alerting values: YAML=z, DB=z	, Merged=)r  r  )r  r  r  )r  r  )r  r  r  setunionr}   re  r  r  r  slack_alerting_instancer  )	r  r  r  r  _general_settings_yaml_alerting_db_alerting_merged_alertingr  s	            rg   r  z0ProxyConfig._add_general_settings_from_db_config  sw    (OO,>C(Z;L-L ,$((T:F/
;TB%))*d;G0<dC "%%5j%A!B"#4Z#@A#'(<(<\(J#K #'(8(D#E 1* =I#3J#?? I $ 
 %**45Ej5Q4RRWXijtXuWvv  AQ  @R  S 0@ ,!//-j9 0  ")#% /@/L ,!//-j9 0  ,d3/@/L ,!//-j9 0  (]>O-O.?.N]+,<],K)55CC,];
 D 
 )&*;;7H&834 55CC%56L%M% D  < *GIs   1Gc           	      d  K   t         y	 t         j                  d       t        j                  d       t
        j                  d      }|ddlm}  |       }t
        j                  d      }|r_ddl	m
} 	 |j                  |      }t         j                  |j                  |t        gdd	t        
       t        j                  d|        yddlm} t
        j                  dd      }	  ||      }	t         j                  |j                  d|	t)        j*                  dd      z   t        gdd	t               t        j                  d|        yy# t        $ r Y ,w xY w# t         $ r t        j"                  d|        Y yw xY w# t         $ r t        j"                  d       Y yw xY ww)z
        Reschedule the spend log cleanup job based on current general_settings.
        This is called when maximum_spend_logs_retention_period is updated dynamically.
        If the retention period is None, the job will be removed.
        Nspend_log_cleanup_jobz&Removed existing spend log cleanup job#maximum_spend_logs_retention_periodr   r   maximum_spend_logs_cleanup_cronCronTriggerTrx  r{  replace_existingmisfire_grace_timez)Spend log cleanup rescheduled with cron: /Invalid maximum_spend_logs_cleanup_cron value: )r   %maximum_spend_logs_retention_interval1dintervalrn   secondsrx  r{  r4  r5  z-Spend log cleanup rescheduled with interval: 3Invalid maximum_spend_logs_retention_interval value)	scheduler
remove_jobr}   rd  rp  r  r  7litellm.proxy.db.db_transaction_queue.spend_log_cleanupr   apscheduler.triggers.cronr2  from_crontabadd_jobcleanup_old_spend_logsr]  r   r  r  *litellm.litellm_core_utils.duration_parserr   rq   randint)
r  retention_periodr   spend_log_cleanupcleanup_cronr2  cron_triggerr   retention_intervalinterval_secondss
             rg   !_reschedule_spend_log_cleanup_jobz-ProxyConfig._reschedule_spend_log_cleanup_job  s     	  !89 %%&NO
 ,//0UV' !0 1+//0QRLA#.#;#;L#IL%%)@@$+_2)-+I &  )--CL>R &6%9%9;T&"':;M'N$%%)@@" 06>>!R3H H+_2)-+I &  )--GHZG[\a (  		: " (..I,X6 " (..Msr   F0*E AF08AE% F0-A&F F0	E"F0!E""F0%!F	F0F		F0F-*F0,F--F0db_general_settingsc                 p  K   |yt        |      }d|v r|d   t        d<   d|v r|d   t        d<   d|v r3|d   t        d<   t        j                  j	                  t        d          d|v r'|d   t        d<   t        t        d          d{    d|v r|d   t        d<   d	|v rh|d	   }|
dt        d	<   nWt        |t              r
|t        d	<   n=t        |t              r|j                         d
k(  t        d	<   nt        |      t        d	<   d|v rW|d   }|nBt        |t              r|a
n/t        |t              r|j                         d
k(  a
nt        |      a
t        t        d<   d|v rBt        j                  d      }|d   }|t        d<   ||k7  r| j                          d{    yyy7 #7 
w)z;
        Pull from DB, read general settings value
        Nmax_parallel_requestsglobal_max_parallel_requestsr  )r  r.  r/  r  store_prompts_in_spend_logsrR  r  r/  )r  r  r  r(  r  r   r  boolr  r  r  r  rL  )r  rM  r)  r  	old_value	new_values         rg   _update_general_settingsz$ProxyConfig._update_general_settingsO  s*    
 & !45"&778I'945 *->>?P.@;<
 //0A/0R_-55CC.? D 
 $'889J(:56 4'78P'Q  
 001BCS1T-. ),==%&CDE}BF !>?E4(BG !>?E3' KKMV+ !!>?
 CGu+ !>? "33%&9:E}E4($)!E3'$)KKMV$;!$(K!4E01 14EE(,,-RSI)*OPIFOBCI%<<>>> & FOZ ?s%   BF6F1DF6)F4*F64F6current_configr  r  r  r  r  db_param_valuec                 >   dt         dt         ddfd}|dk(  r}| j                  |d      }i }|j                         D ]2  \  }}|||<   |j                         }	|||	<   |t        j
                  |	<   4 |j                  di       j                  |       |S |d	k(  rBt        |t               r2|j                         D ]  \  }}|t        v st        t        ||       ! ||vr|||<   |S t        ||   t               rt        |t               r |||   |       |S |||<   |S )
am  
        Updates the config fields with the new values from the DB

        Args:
            current_config (dict): Current configuration dictionary to update
            param_name (Literal): Name of the parameter to update
            db_param_value (Any): New value from the database

        Returns:
            dict: Updated configuration dictionary
        dstsrcr.  Nc                 J   | |fg}|r|j                         \  }}|j                         D ]r  \  }}|	t        |t              rt	        |      dk(  r(t        |t
              r6t        |j                  |      t
              r|j                  ||   |f       n|||<   t |ryy)z
            Deep-merge src into dst, skipping None values and empty lists from src.
            On conflicts, src (DB) wins, but empty lists are treated as "no value" and don't overwrite.
            Nr   )r  r  r  r  rn  r  r  r  )rZ  r[  stackdrN  r  r  s          rg   _deep_merge_dictsz<ProxyConfig._update_config_fields.<locals>._deep_merge_dicts  s    
 3ZLEyy{1GGI 
!DAqy !!T*s1v{ !!T*z!%%(D/IadAY/ !
! ri   r  T)r  r  )r  r  r  upperr  r  
setdefaultrJ  r  r#   rV  rg  )
r  rV  r  rX  r_  r  merged_env_varsr  r  	upper_keys
             rg   _update_config_fieldsz!ProxyConfig._update_config_fields  sa   .	!4 	!d 	!t 	!( 00!%!G!Gd "H "
 %'O0668 .
U',$IIK	-2	*(-

9%	. %%&=rBII "!--*^T2R,224 1
U==GS%0	1 ^+)7N:&!! nZ0$7JD=
 nZ8.I
  *8N:&ri   r  c                   K   |durt        j                  d       |S g }g d}|D ]'  }|j                  d|d      }|j                  |       ) t	        j
                  |  d {   }|D ]T  }|t        |dd       }	t        |dd       }
t        j                  d|	 d	|
        |	>|
A| j                  ||	|

      }V |S 7 _w)NTz4'store_model_in_db' is not True, skipping db updatesrW  r  r~  )r  r  r  r   zparam_name=z, param_value=)rV  r  rX  )	r}   rd  get_generic_datar  r  gatherr  re  rd  )r  r]  r~  r  _tasksr  r  responser  r  r   s              rg   r  z"ProxyConfig._update_config_from_db  s     D( %%F M
  	$A$55 h 6 H MM(#		$ "..&11	! 	H <>J!(M4@K &&j\}E %+*A33#))#. 4 	" % 2s   A#C%C&AC*C-Cobject_typec                     t         j                  dd      }|yt        |t              s#t	        j
                  dt        |       d       yt        |      t        fd|D              S )aD  
        Check if an object type should be loaded from the database based on general_settings.supported_db_objects.

        Args:
            object_type: Type of object to check (e.g., SupportedDBObjectType.MODELS, "models", etc.)

        Returns:
            True if the object should be loaded, False otherwise
        supported_db_objectsNTz(supported_db_objects is not a list, got z. Loading all objects.c              3   :   K   | ]  }t        |      k(    y wrP  )r  )rM  objobject_type_strs     rg   rO  z5ProxyConfig._should_load_db_object.<locals>.<genexpr>>  s     O33s8.Os   )	r  r  r  r  r}   r|  rV   r  r1  )r  rj  rl  ro  s      @rg   _should_load_db_objectz"ProxyConfig._should_load_db_object  sx      0334JDQ  ' .5 ((:4@T;U:VVlm  k* O:NOOOri   c                    K   	 |j                   j                  j                          d {   }|S 7 # t        $ r:}t	        j
                  dj                  t        |                   g }Y d }~|S d }~ww xY ww)NzQlitellm.proxy_server.py::add_deployment() - Error getting new models from DB - {})r  litellm_proxymodeltable	find_manyrp  r}   r  ru   r  )r  r]  r  r  s       rg   _get_models_from_dbzProxyConfig._get_models_from_db@  su     	,//GGQQSSJ  T 	 **cjjF
 J	s6   A:'4 24 A:4 	A7/A2,A:2A77A:c                   K   	 | j                  d      r5| j                  |       d{   }| j                  ||       d{    |j                  j                  j                  ddi       d{   }|$| j                  |j                  	       d{    | j                  |       d{    y7 7 w7 I7 %7 # t        $ r7}t        j                  d
j                  t        |                   Y d}~yd}~ww xY ww)z{
        - Check db for new models
        - Check if model id's in router already
        - If not, add to router
        modelsrj  r]  N)r  r  r  r  r  )rM  z>litellm.proxy.proxy_server.py::ProxyConfig:add_deployment - {})rp  rt  r  r  r  r  rU  r   _init_non_llm_objects_in_dbrp  r}   r  ru   r  )r  r]  r  r  rM  r  s         rg   add_deploymentzProxyConfig.add_deploymentM  s'    	**x*@#'#;#;-#;#XX
 --)=N .    )6(8(8(G(G(R(R#%78 )S ) #
 #.33(;(G(G 4   
 222OOO% Y#
 P 	 **PWWF 	s   D	'C B<C B>/C 6C 7%C CC 6C7C ;D	<C >C  C C C 	D-D<D	DD	c                   K   | j                  d      r| j                  |       d{    | j                  d      r| j                  |       d{    | j                  d      r| j                  |       d{    | j                  d      r| j	                  |       d{    | j                  d      r| j                          d{    | j                  d	      r| j                  |       d{    | j                  d
      r| j                          d{    | j                  d      r| j                  |       d{    | j                  d      r| j                  |       d{    | j                  d      r| j                  |       d{    | j                  d      r| j                  |       d{    | j                  d      r| j                  |       d{    | j                  d      r| j                  |       d{    | j                  d      r!ddlm} |j!                  ||        d{    | j                  d      r| j#                  |       d{    | j                  d      r| j%                  |       d{    yy7 7 u7 L7 #7 7 7 7 7 Z7 17 7 7 7 7 Y7 /w)z
        Use this to read non-llm objects from the db and initialize them

        ex. Vector Stores, Guardrails, MCP tools, etc.
        r  rw  rx  Nr  vector_storesvector_store_indexesmcpagentsr.  rF  r  toolsmodel_cost_mapanthropic_beta_headerssso_settingscache_settingsr   )CacheSettingsManager)r]  r  semantic_filter_settingsconfig_overrides)rp  _init_guardrails_in_db_init_policies_in_db_init_vector_stores_in_db _init_vector_store_indexes_in_db_init_mcp_servers_in_db_init_agents_in_db"_init_pass_through_endpoints_in_db_init_prompts_in_db_init_search_tools_in_db_init_tool_policy_in_db _check_and_reload_model_cost_map(_check_and_reload_anthropic_beta_headers_init_sso_settings_in_db;litellm.proxy.management_endpoints.cache_settings_endpointsr  init_cache_settings_in_db$_init_semantic_filter_settings_in_db%_init_hashicorp_vault_config_override)r  r]  r  s      rg   ry  z'ProxyConfig._init_non_llm_objects_in_dbw  s      &&<&@--M-JJJ&&:&>++-+HHH&&?&C00}0MMM&&3I&J77m7TTT&&5&9..000&&8&<)))FFF&&3K&L99;;;&&9&=***GGG&&>&B//m/LLL&&7&;..].KKK&&3C&D77m7TTT&&3K&L??+ @    &&>&B//m/LLL&&3C&D '@@+$ A    &&3M&N;;-;XXX&&3E&F<<+ =    Gg K I N U 1 G < H M L U
 M
 Ys  (K3K+K3K+K3K+K3.K/)K3K+K3K)K3.K/+K3K+K3K +K32K#3+K3K&+K3
K)+K36K+72K3)K-*+K3K/+K3K1K3K3K3K3K3K3K3K3 K3#K3&K3)K3+K3-K3/K31K3c                 2  K   ddl }ddl}ddlm} 	 |j                  j
                  j                  ddi       d{   }||j                  y|j                  }t        |t              r |j                  |      }|j                  dd      }|yt        | d      r| j                  |k(  r|j                  j                  |      }|rN|D ]I  }	t        |	|      s|	j                   |	j                   j"                  4t%        j&                  d	        y t%        j(                  d
       |j                  j+                  |j,                  |       |j                  dd      rR|j/                  |t0               d{   }
|
rF|j                  j3                  |
       t%        j(                  d       nt%        j(                  d       |j5                         | _        y7 7 e# t6        $ r"}t%        j8                  d|        Y d}~yd}~ww xY ww)z
        Initialize MCP semantic filter settings from database.
        Called periodically (approximately every 10 seconds) by background task to hot-reload settings across all pods.
        r   NSemanticToolFilterHookr  r  r  mcp_semantic_tool_filterr  z=Semantic filter settings unchanged, skipping reinitializationzYSemantic filter settings unchanged, but hook is missing or uninitialized. Reinitializing.ra  Fr~  r  z)MCP Semantic Filter reinitialized from DBzMCP Semantic Filter disabledz5Error initializing semantic filter settings from DB: )r  rg  'litellm.proxy.hooks.mcp_semantic_filterr  r  r  find_uniquer   r  r  r  r  r  r  r  get_custom_loggers_for_typefiltertool_routerr}   re  rd  remove_callbacks_by_typer  initialize_from_configr  r  rl  rp  r  )r  r]  r  rg  r  config_recordr  mcp_semantic_filter_configactive_hooksactive_hookhookr  s               rg   r  z0ProxyConfig._init_semantic_filter_settings_in_db  s&    
 	RF	"/"2"2"A"A"M"M#%78 #N # M $(A(A(I,88*C0#-4::.>#? )9)=)=*D*& *1 t;<448RR  88TT2 !
 $+7 	+K)+7MN$/$6$6$B(3(:(:(F(F(R$8$>$>(g%& %+	+ )--s
 ,,EE!!#9
 *--i?3JJ5) K   44II$O(--C %))*HI 1K0O0O0QD-d  	 **GsK 	s   H+G) G$G) HAG) HA	G) G) +G) G) HA(G) G'A!G) #H$G) 'G) )	H2H
HHHc                 L  K   	 |j                   j                  j                  ddi       d{   }||j                  j	                  dd       |j                  j	                  dd       |j                  j	                  dd       |j                  j                         D ci c]  \  }}|j                         | }}}| j                  |       yy7 c c}}w # t        $ r7}t        j                  d	j                  t        |                   Y d}~yd}~ww xY ww)
zS
        Initialize SSO settings from database into the router on startup.
        r{  
sso_configr  Nrole_mappingsteam_mappingsr  r  zHlitellm.proxy.proxy_server.py::ProxyConfig:_init_sso_settings_in_db - {})r  litellm_ssoconfigr  r  r  r  r`  r  rp  r}   r  ru   r  )r  r]  r  r  r  uppercase_sso_settingsr  s          rg   r  z$ProxyConfig._init_sso_settings_in_db  s#    
	!.!1!1!C!C!O!O\* "P " L '))--otD))--otD))--.>E '3&?&?&E&E&G*"U IIK&*& * 66*@ 7  (*  	 **ZaaF 	sQ   D$+C! CA7C! 'CC! D$C! C! !	D!*-DD$D!!D$c                 j  K   ddl m}m}m}m}m} 	 |j                  j                  j                  ddi       d{   }||j                  | j                   ||        y ||j                        }| j                  |k(  ry| j                  |      }	 ||      }
 ||	       	 | j                  d       |j                         | _
        t        j                   d       y7 # t        $ r
  ||
        w xY w# t        $ r)}t        j"                  d	t%        |             Y d}~yd}~ww xY ww)
z
        Load Hashicorp Vault config override from DB.
        Decrypts sensitive fields, sets HCP_VAULT_* env vars, and reinitializes the secret manager.
        Called periodically via _init_non_llm_objects_in_db to sync config across pods.
        r   )HASHICORP_ENV_VAR_MAPPING_clear_hashicorp_vault_state_get_current_env_values_parse_config_value_set_env_varsconfig_typehashicorp_vaultr  N)r"  z.Hashicorp Vault config override loaded from DBz9Error loading Hashicorp Vault config override from DB: %s)<litellm.proxy.management_endpoints.config_override_endpointsr  r  r  r  r  r  litellm_configoverridesr  config_valuer  r  rY  rp  rl  r}   re  r  r  )r  r]  r  r  r  r  r  	db_recordr  decrypted_dataprevious_envr  s               rg   r  z1ProxyConfig._init_hashicorp_vault_config_override#  s@    	
 	
%	+..FFRR$&78 S  I  I$:$:$B44@06-i.D.DEK 00K? "77DN 33LML.)..EV.W 1<0@0@0BD- &&'WX?2  l+  	 **KA 	sn   D3+C> C&&C> $D3%!C> D3!C> )C( ;*C> %D3&C> (C;;C> >	D0D+&D3+D00D3c           
        K   	 |j                   j                  j                  ddi       d{   }||j                  y|j                  }|j	                  d      }|j	                  dd      }||du ryt        j                         }d}|rd}t        j                  d	       nu|st        V	 t        j                  t              }||z
  }	|	j                         d
z  }
|
|k\  rd}t        j                  d|
dd|        nd}t        j                  d       |rddlm} t         j"                  } ||      }|t         _        t'                t!        j(                  |       |j+                         a	|j                   j                  j-                  ddidt/        |dd      ddt/        |dd      id       d{    t        j                  d|rt1        |      nd        yy7 # t        $ r$}t        j                  d|        d}Y d}~d}~ww xY w7 ^# t        $ r+}t        j2                  dt5        |              Y d}~yd}~ww xY ww)z
        Check if model cost map needs to be reloaded based on database configuration.
        This function runs every 10 seconds as part of _init_non_llm_objects_in_db.
        r  model_cost_map_reload_configr  Ninterval_hoursforce_reloadFTz4Model cost map reload triggered by force reload flagr  zFModel cost map reload triggered by interval. Hours since last reload: r1  , Interval:  Error parsing last reload time: zBModel cost map reload triggered - no previous reload time recordedr   get_model_cost_mapr  r  r  r  r  r   r   createrJ  r  r  z4Model cost map reloaded successfully. Models count: z+Error in _check_and_reload_model_cost_map: )r  r  r  r   r  r   utcnowr}   rd  last_model_cost_map_reloadfromisoformattotal_secondsrp  r|  -litellm.litellm_core_utils.get_model_cost_mapr  rg  model_cost_map_url
model_costrO   add_known_models	isoformatupsertr'   rn  r  r  )r  r]  r  r~  r  r  current_timeshould_reloadlast_reload_timetime_since_last_reloadhours_since_last_reloadr  r  r  new_model_cost_maps                  rg   r  z,ProxyConfig._check_and_reload_model_cost_mapX  s    
j	"/"2"2"A"A"M"M#%CD #N # M $(A(A(I"..F#ZZ(89N!::ne<L%,%*?#??,L "M $$))J  + .9-+3+A+A6,( 2>@P1P.2@@BTI 0 3nD,0M055"h  jA  BE  iF  FR  Sa  Rb  !c %)M(--\  &-%?%?"%7<N%O"%7"46 ((8JK .:-C-C-E* $&&55<<')GH +I+56D49!",# *:6D49!",# =   . %))Jfx3OaKb~  KA  BU oT % -,44>qcB )--@6  	 **=c!fXF 	s   I+H' G2H' I5H' 8I98H' 2AG5 C H' H%)H' 0I2H' 5	H">HH' H""H' '	I0!IIIIc           
      l  K   	 |j                   j                  j                  ddi       d{   }||j                  y|j                  }|j	                  d      }|j	                  dd      }||du ryt        j                         }d}|rd}t        j                  d	       nu|st        V	 t        j                  t              }||z
  }	|	j                         d
z  }
|
|k\  rd}t        j                  d|
dd|        nd}t        j                  d       |rddlm}  |       }|j!                         a	|j                   j                  j#                  ddidt%        |dd      ddt%        |dd      id       d{    t'        d |j)                         D              }t        j                  d|        yy7 # t        $ r$}t        j                  d|        d}Y d}~d}~ww xY w7 q# t        $ r+}t        j*                  dt-        |              Y d}~yd}~ww xY ww)z
        Check if anthropic beta headers config needs to be reloaded based on database configuration.
        This function runs every 10 seconds as part of _init_non_llm_objects_in_db.
        r  $anthropic_beta_headers_reload_configr  Nr  r  FTz<Anthropic beta headers reload triggered by force reload flagr  zNAnthropic beta headers reload triggered by interval. Hours since last reload: r1  r  r  zJAnthropic beta headers reload triggered - no previous reload time recordedr   reload_beta_headers_configr  r  r   r  r  c              3   4   K   | ]  }|d k7  r	|dk7  rd  yw)provider_aliasesr  r  Nr^  rM  r  s     rg   rO  zGProxyConfig._check_and_reload_anthropic_beta_headers.<locals>.<genexpr>-  s(      %..13E %s   z@Anthropic beta headers config reloaded successfully. Providers: z3Error in _check_and_reload_anthropic_beta_headers: )r  r  r  r   r  r   r  r}   rd  "last_anthropic_beta_headers_reloadr  r  rp  r|  &litellm.anthropic_beta_headers_managerr  r  r  r'   rV  r  r  r  )r  r]  r  r~  r  r  r  r  r  r  r  r  r  r  provider_counts                  rg   r  z4ProxyConfig._check_and_reload_anthropic_beta_headers  s    i	"/"2"2"A"A"M"M#%KL #N # M $(A(A(I"..F#ZZ(89N!::ne<L%,%*?#??,L "M $$))R  + 6A-+3+A+A>,( 2>@P1P.2@@BTI 0 3nD,0M055"p  rI  JM  qN  NZ  [i  Zj  !k %)M(--d  89
 6B5K5K5M2 $&&55<<')OP +Q+56D49!",# *:6D49!",# =   0 "% %'__.% "
 %))VWeVfgS oT % -,44>qcB )--2B  	 **Ec!fXN 	s   H4+G= GG= H45G= 8H498G= 2AG BG= 	G;
<G= H4G= 	G8G3.G= 3G88G= =	H1!H,'H4,H11H4c                      ddl m}  ||      S )a5  
        Convert a DB prompt object to a PromptSpec object.

        Handles the versioning of the prompt, if the DB prompt has a version, it will be used to create the versioned prompt_id.

        Args:
            db_prompt: The DB prompt object

        Returns:
            The PromptSpec object
        r   )create_versioned_prompt_spec	db_prompt)&litellm.proxy.prompts.prompt_endpointsr  )r  r  r  s      rg   _get_prompt_spec_for_db_promptz*ProxyConfig._get_prompt_spec_for_db_prompt;  s     	X+i@@ri   c                 ^  K   ddl m} ddlm} 	 |j                  j
                  j                          d {   }|D ]&  }| j                  |      }|j                  |       ( y 7 0# t        $ r7}t        j                  dj                  t        |                   Y d }~y d }~ww xY ww)Nr   )IN_MEMORY_PROMPT_REGISTRY)
PromptSpecr  )promptzClitellm.proxy.proxy_server.py::ProxyConfig:_init_prompts_in_db - {})%litellm.proxy.prompts.prompt_registryr  "litellm.types.prompts.init_promptsr  r  litellm_prompttablers  r  initialize_promptrp  r}   re  ru   r  )r  r]  r  r  prompts_in_dbr  prompt_specr  s           rg   r  zProxyConfig._init_prompts_in_dbK  s     SA	"/"2"2"F"F"P"P"RRM' P"AAFAS);;;;OP S
  	 &&U\\F 	s>   B-'A* A(/A* 'B-(A* *	B*3-B% B-%B**B-c                 d  K   ddl m}m}m} 	 |j	                  |       d {   }t        j                  dt        |             |D ]  }|j                  t        ||               y 7 G# t        $ r7}t        j                  dj                  t        |                   Y d }~y d }~ww xY ww)Nr   )IN_MEMORY_GUARDRAIL_HANDLER	GuardrailGuardrailRegistryrx  zguardrails from the DB %s)	guardrailzFlitellm.proxy.proxy_server.py::ProxyConfig:_init_guardrails_in_db - {})+litellm.proxy.guardrails.guardrail_registryr  r  r  get_all_guardrails_from_dbr}   re  r  sync_guardrail_from_dbr   rp  r  ru   )r  r]  r  r  r  guardrails_in_dbr  r  s           rg   r  z"ProxyConfig._init_guardrails_in_db\  s     	
 	
	 (BB+ C   
 !&&+S1A-B . 	+BB"9i8 C   	 **X__F 	s?   B0A- A+AA- *B0+A- -	B-6-B(#B0(B--B0c                 b  K   ddl m} ddlm} 	  |       } |       }|j	                  |       d{    |j                  |       d{    t        j                  d       y7 47 # t        $ r7}t        j                  dj                  t        |                   Y d}~yd}~ww xY ww)zi
        Initialize policies and policy attachments from database into the in-memory registries.
        r   )get_attachment_registry)get_policy_registryrx  Nz4Successfully synced policies and attachments from DBzDlitellm.proxy.proxy_server.py::ProxyConfig:_init_policies_in_db - {})/litellm.proxy.policy_engine.attachment_registryr   +litellm.proxy.policy_engine.policy_registryr  sync_policies_from_dbsync_attachments_from_dbr}   re  rp  r  ru   r  )r  r]  r   r  policy_registryattachment_registryr  s          rg   r  z ProxyConfig._init_policies_in_dbw  s     	
 	T	13O"9"; "77m7TTT &>>+ ?    !&&F U  	 **V]]F 	sP   B/#A, A(A, A*A, 'B/(A, *A, ,	B,5-B'"B/'B,,B/c                   K   ddl m} 	  |       }|j                  |       d{    t        j                  d       y7 # t
        $ r7}t        j                  dj                  t        |                   Y d}~yd}~ww xY ww)z
        Initialize tool policy from database into the in-memory registry.
        Synced periodically by add_deployment -> _init_non_llm_objects_in_db.
        r   )get_tool_policy_registryrx  Nz'Successfully synced tool policy from DBzGlitellm.proxy.proxy_server.py::ProxyConfig:_init_tool_policy_in_db - {})	%litellm.proxy.db.tool_registry_writerr	  sync_tool_policy_from_dbr}   re  rp  r  ru   r  )r  r]  r	  registryr  s        rg   r  z#ProxyConfig._init_tool_policy_in_db  s|     
 	S		/1H33-3PPP &&'PQ Q 	 **Y``F 	s>   BA AA  BA 	B-A>9B>BBc                   K   ddl m} 	 |j                  |       d {   }t        |      dk  ry t        j
                   ||      t        _        y |D ]"  }t        j
                  j                  |       $ y 7 ^# t        $ r7}t        j                  dj                  t        |                   Y d }~y d }~ww xY ww)Nr   r  rx  )r|  )vector_storeIlitellm.proxy.proxy_server.py::ProxyConfig:_init_vector_stores_in_db - {})r  r  _get_vector_stores_from_dbrn  rg  r  add_vector_store_to_registryrp  r}   r  ru   r  )r  r]  r  r|  r  r  s         rg   r  z%ProxyConfig._init_vector_stores_in_db  s     S	"5"P"P+ #Q # M =!Q&,,40C"/1- %2 L11NN%1 O   	 **[bbF 	T   CB  A>B  C"B  C'B  =C>B   	C 	-B;6C;C  Cc                   K   ddl m} 	 |j                  |       d {   }t        |      dk  ry t        j
                   ||      t        _        y |D ]"  }t        j
                  j                  |       $ y 7 ^# t        $ r7}t        j                  dj                  t        |                   Y d }~y d }~ww xY ww)Nr   )VectorStoreIndexRegistryrx  )r}  )vector_store_indexr  )r  r  !_get_vector_store_indexes_from_dbrn  rg  vector_store_index_registryupsert_vector_store_indexrp  r}   r  ru   r  )r  r]  r  r}  r  r  s         rg   r  z,ProxyConfig._init_vector_store_indexes_in_db  s     X	 /PP"/ Q   ! '(A-22:6N)=73 +? &77QQ+= R "  	 **[bbF 	r  c                   K   ddl m}  |       st        j                  d       y ddlm} 	 |j                          d {    y 7 # t        $ r7}t        j                  dj                  t        |                   Y d }~y d }~ww xY ww)Nr   )is_mcp_availablez<MCP module not available, skipping MCP server initializationr  zGlitellm.proxy.proxy_server.py::ProxyConfig:_init_mcp_servers_in_db - {}),litellm.proxy._experimental.mcp_server.utilsr  r}   re  r  r  reload_servers_from_databaserp  r  ru   r  )r  r  r  r  s       rg   r  z#ProxyConfig._init_mcp_servers_in_db  sx     Q! &&N 	
	+HHJJJ 	 **Y``F 	s@   *BA  AA BA 	B-B>BBBc                   K   ddl m} 	 |j                  |       d {   }|j                  |t               y 7 # t
        $ r7}t        j                  dj                  t        |                   Y d }~y d }~ww xY ww)Nr   r   rx  )	db_agentsr  zBlitellm.proxy.proxy_server.py::ProxyConfig:_init_agents_in_db - {})
,litellm.proxy.agent_endpoints.agent_registryr   get_all_agents_from_dbload_agents_from_db_and_configr  rp  r}   r  ru   r  )r  r]  AGENT_REGISTRYr  r  s        rg   r  zProxyConfig._init_agents_in_db  s     	
	,CC+ D  I 99#- :   	 **T[[F 	s7   B> <> B> 	A>-A94B9A>>Bc                 .  K   ddl m} ddlm} 	 |j	                  |       d{   }t        j                  dt        |       d       t        |      dkD  r^t        B|j                  t        |       d{    t        j                  d	t        |       d
       yt        j                  d       yt        j                  d       y7 7 U# t        $ r7}t        j                  dj                  t        |                   Y d}~yd}~ww xY ww)z
        Initialize search tools from database into the router on startup.
        Only updates router if there are tools in the database, otherwise preserves config-loaded tools.
        r   )SearchToolRegistry)SearchAPIRouterrx  NzLoading z) search tool(s) from database into router)router_instancer  zSuccessfully loaded z search tool(s) into routerzMRouter not initialized yet, search tools will be added when router is createdzNNo search tools found in database, keeping config-loaded search tools (if any)zHlitellm.proxy.proxy_server.py::ProxyConfig:_init_search_tools_in_db - {})3litellm.proxy.search_endpoints.search_tool_registryr$  &litellm.router_utils.search_api_routerr%  get_all_search_tools_from_dbr}   rd  rn  r  update_router_search_toolsre  rp  r  ru   r  )r  r]  r$  r%  r  r  s         rg   r  z$ProxyConfig._init_search_tools_in_db  s    	
 	K"	!3!P!P+ "Q " L !%%3|,--VW < 1$))DD(2 E    )--.s</@.AA\] )..g %**d1  	 **ZaaF 	si   DC CAC :C;&C !D"C 7D8C DC C 	D-DDDDc                 :   K   ddl m}  |        d {    y 7 w)Nr   )'initialize_pass_through_endpoints_in_db);litellm.proxy.pass_through_endpoints.pass_through_endpointsr,  )r  r,  s     rg   r  z.ProxyConfig._init_pass_through_endpoints_in_db;  s     	
 6777s   r  c                    t        |t              rt        di |}n)t        |t              rt        di |j	                         }i }j
                  j                         D ]  \  }}t        ||      xs |||<    ||_        |S )Nr  r  r^  )r  r  r  r   r  credential_valuesr  r   )r  r  credential_objectdecrypted_credential_valuesr  r  s         rg   decrypt_credentialszProxyConfig.decrypt_credentialsB  s    j$' . < <
I. . I1F1F1H I&(#%77==? 	WDAq-Aq-Q-VUV'*	W /J+  ri   db_credentialsc                   K   | j                  t               d{   }| j                  |      }||z   }g }t        t        j
                        D ]=  \  }}|j                  |D cg c]  }|j                   c}vs-|j                  |       ? t        |d      D ]!  }t        j
                  j                  |       # y7 c c}w w)z
        Create all-up list of db credentials + local credentials
        Compare to the litellm.credential_list
        Delete any from litellm.credential_list that are not in the all-up list
        r  Nr  T)reverse)
r  rR  r  rU  rg  r  credential_namer  sortedr  )	r  r4  r~  r  combined_listidx_to_deleterp  r  r  s	            rg   delete_credentialszProxyConfig.delete_credentialsO  s      8MNN3363B '8 ()@)@A 	*OC))1>2)-$$2  $$S)		*
 -6 	-C##'',	- O2s)   CCAC(C;C ACCc                   K   	 |j                   j                  j                          d {   }|D cg c]  }| j                  |       }}| j	                  |       d {    t        j                  |       y 7 Qc c}w 7 !# t        $ r9}t        j                  dj                  t        |                   g cY d }~S d }~ww xY ww)NzSlitellm.proxy_server.py::get_credentials() - Error getting credentials from DB - {})r  litellm_credentialstablers  r3  r;  r   upsert_credentialsrp  r}   r  ru   r  )r  r]  credentialsr  r  s        rg   get_credentialszProxyConfig.get_credentialsf  s     	 - 0 0 I I S S UUKFQRd433D9RKR))   11 VR  	 **ellF
 I	sa   C'B A=B A?B "B#B <C=B ?B 	C.C=C>CCC)r.  NrP  F)]r^   r  r  __doc__r  r  rR  r  r  r  r   r  r  r  r   r(  r  r
   r	   r  r  r  r  r  r  r  r  r  r  r  r  r   __annotations__r  rg  r{   r  re  rc  rZ  rY  r  r  r  r  r  r  r   r   r  r   r  r  r  r  r  staticmethodr   r  r   r  r  r  rL  rU  rd  r  r   rB   rp  rt  rz  ry  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r   r3  r;  r@  r^  ri   rg   r|  r|  	  s   ?U U UN N N 15& (&	&P% % % %N(MD (MV *+=V###&#7:#	#J tDz d  &@@0&9# 9$ 9v$  4 D4H 7D 7D(4@S;T2U 7Dv#s3x "&$ &P]
Aw~~.]
ABE]
A~0&$ 0&d(
(
  /(
 X&	(
T* *^ +/9K'}9K #3-9Kv @@#$ @#3 @#D/ /# /bT d >H
TNH
 (H
TPP '"678P !	P
 
P2 $ D PT"%)"?G}"	" JO"%)"BF"	"2
#D 
#T 
# C HTN  > 7;	0#$450  -0 $N3	0
 
$0d+G+G V$+G  -	+G
 
+GZFF37FLXF	FPIVL?(4. L?\RR %
R R 
Rh+#+ + $D>	+Z P &;!;< P	 PD|  (#( ((T=| =~P PdL 63 3joL obp)pdA | ", 6 @< $\ 6L <,l &.L .`8!eD)O.D ! !-tN7K -.< ri   r|  c                  R    dd l } |j                  |       t        j                  d<   y )Nr   r  )r  dumpsr  r  )r  r  s     rg   save_worker_configrG  |  s    ",$**T"2BJJri   c                 :  K   ddl m}  |        t        j                  dd      j	                         dk7  r
t                | a|a|du rddd l}ddl	m
}m}m} |j                  |j                          |j                  |j                          |j                  |j                         |du redd l}ddl	m
}m}m} |j                  |j                          |j                  |j                          |j                  |j                         n|d	u r|d	u rt        j                   j#                  d
d      }||j%                         dk(  rGdd l}ddl	m}m}  |j                  |j                          |j                  |j                         nw|j%                         dk(  rddd l}ddl	m
}m}m} |j                  |j                          |j                  |j                          |j                  |j                         di t        i i}|r't&        j)                  t*        |       d {   \  aaa|r|a||t           d<   |r|a||t           d<   |r|t        j                   d<   |r||t           d<   |r|a||t           d<   |r|a||t           d<   |r||t           d<   |du rdt8        _        d|d   d<   |du rdt8        _        d|d   d<   |	r*t?        |	      t8        _         t8        j@                  |d   d<   tB        r	 |
a"y 7 ݭw)Nr   )show_bannerLITELLM_DONT_SHOW_FEEDBACK_BOXr  rR  T)verbose_loggerr}   r~   )levelFLITELLM_LOGINFOr|   DEBUGgeneralr  r%  r:  AZURE_API_VERSION
max_tokenstemperaturerequest_timeoutaliasdrop_paramsadd_function_to_promptr  )#!litellm.proxy.common_utils.bannerrI  r  r  r  rw   
user_model
user_debuglogginglitellm._loggingrK  r}   r~   setLevelrN  rO  r  r  r`  r  r  r  r  r  user_headersuser_api_baseuser_temperatureuser_request_timeoutrg  rV  rW  r  r  experimentaluser_telemetry)r9  rU  r:  api_versionre  detailed_debugrS  rR  rT  r  	telemetryrV  rW  r%  save	use_queuer~  rI  r[  rK  r}   r~   litellm_log_settingdynamic_configs                           rg   r  r    s    ( >M	yy126<<>&HJJ}	
 	
 	gll3&&&W\\:%%%GLL9	
 	
 	gmm4&&&W]];%%%GMM:	%Ne3 jjnn]B?*"((*f4X /%..!,, .$--!,, %**,7  ''gmm'<.%..!-- .$--!--  Z4N
 ***v*VV		
07z"9- 19z":.  	

	
 3=z"<0&4?z"=1.8Gz"#45.3z"7+d"37y!-0%)-&>By!":;":.292D2Dy!,/NA Ws   H9L;L<CLc              #     K   t        j                  d       | D ]B  }t        j                  d|       	 dt        j                  |j	                                d D y # t
        $ r dt        j                  |       d Y lw xY ww)Ninside generatorzreturned chunk: %sdata: rN  )r}   re  r  rF  r  rp  )ri  chunks     rg   data_generatorro    s     12 3""#7?	34::ejjl34D993  	34::e,-T22	3s(   1B
)A B
 $BB
BB
r  request_datac                  K   t        j                  d       	 t        j                          | 4 d {   }t        j	                  |||       d {   }|2 3 d {   }|j                  d      }	 d| d &7 L7 .7 %# t        $ r}dt        |       d Y d }~Ld }~ww xY w6 d d d       d {  7   n# 1 d {  7  sw Y   nxY wd}d| d y # t        $ r}t        j                  dj                  t        |                   t        j                  |||	       d {  7   t        j                  d
| d       t        |t              r|t        |      }t        t        |d|      t        |dd      t        |dd      t        |dd            }t        j                   d|j#                         i      }	d|	 d Y d }~y d }~ww xY ww)Nrl  )r  ri  r  Tr  rm  rN  [DONE]zTlitellm.proxy.proxy_server.async_assistants_data_generator(): Exception occured - {}r  original_exceptionrp  [1;31mAn error occurred: P

 Debug this by setting `--debug`, e.g. `litellm --model gpt-3.5-turbo --debug`r`   rV   Noner  r#    r`   rV   r  r'  r  )r}   re  r  r  async_post_call_streaming_hookmodel_dump_jsonrp  r  r  ru   post_call_failure_hookr  r'  r?   r  r  rF  r&  )
ri  r  rp  rn  cr  done_message	error_msgproxy_exceptionerror_returneds
             rg   async_assistants_data_generatorr    s     122,		 	0 	0u+JJ"3! K  E ! 0 0a%%4%80"1#T**	00 ! 0"3q6($///0	 !	0 	0 	0 	0 	0"  |nD)) ,&&biiA	

  66/ % 7 
 	
 	

 	""+A3  /A  B	
 a'G
 AI(Ay)4FF+!Wf-M3/	
 Wo.E.E.G$HI~&d+++;,s   G%C" B C" CBCB.BB."C6	B?C C" CB.	B+B&!C&B++C/C" :B=;C" CC
CC" !G%"	G"+AG3D64B$GG%G""G%c                     | j                  d      }t        |t              r|S | j                  d      }t        |t              r|S dS )a  
    Prefer the original client-requested model (pre-alias mapping) when available.

    Pre-call processing can rewrite `request_data["model"]` for aliasing/routing purposes.
    The OpenAI-compatible public `model` field should reflect what the client sent.
    _litellm_client_requested_modelr9  r  )r  r  r  )rp  requested_models     rg   )_get_client_requested_model_for_streamingr  D  sI     #&&'HIO/3'"&&w/O(#>?FBFri   rn  requested_model_from_clientmodel_mismatch_loggedc           
      @   |rt        | t        t        f      s| |fS t        |      r| |fS |j	                  dd      r| |fS t        | t              r| j	                  d      nt        | dd       }|s.||k7  r)t        j                  d|j	                  d      ||       d}t        | t              r	|| d<   | |fS 	 t        | d|       | |fS # t        $ rI}t        j                  d|j	                  d      |t        |       t        |      d       Y d }~| |fS d }~ww xY w)	Nfastest_responseFr9  zolitellm_call_id=%s: streaming chunk model mismatch - requested=%r downstream=%r. Overriding model to requested.litellm_call_idTzPlitellm_call_id=%s: failed to override chunk.model=%r on chunk_type=%s. error=%sr  )r  r   r  r   r  r  r}   re  rV  rp  r  rV   r  )rn  r  rp  r  downstream_modelr  s         rg   _restamp_streaming_chunk_modelr  S  sS    'jD@Q.R+++ &&AB+++ *E2+++ )5		'75'SW;X  !%59T%T""}./'		
 !%%4g+++

w ;< '''  
""^./'KF	
 	
 '''
s   :C 	D<DDc                  K   t        j                  d       	 d }t        |      }d}d}t        j	                  || |      2 3 d {   }t        j                  ||||r|nd        d {   }t        |t        t        f      rt        j                  |      }||z  }t        ||||      \  }}t        |t              r|j                  d	d	
      }n%t        |t              r|j                  d      r|} n	 d| d || d}
d|
 d t7        j8                  d	      5  t;        | d      r	 | j=                          d {    d d d        y 7 7 # t         $ r}	dt        |	       d Y d }	~	Bd }	~	ww xY w6 # t         $ r}	t        j"                  dj%                  t        |	                   t        j'                  ||	|       d {  7   t        j                  d|	 d       t        |	t(              r|	t        |	t*              rt        |	      }nt        |	      }t-        t/        |	d|      t/        |	dd      t/        |	dd      t/        |	dd            }t1        j2                  d|j5                         i      }d| d Y d }	~	d }	~	ww xY w7 _# t>        $ r!}	t        j                  d|	       Y d }	~	d }	~	ww xY w# 1 sw Y   y xY w# t7        j8                  d	      5  t;        | d      rG	 | j=                          d {  7   n,# t>        $ r }	t        j                  d|	       Y d }	~	nd }	~	ww xY wd d d        w # 1 sw Y   w xY wxY ww)Nrl  )rp  Fr  r  ri  rp  )r  ri  r  
str_so_far)response_obj)rn  r  rp  r  T)r  exclude_unsetrm  rN  rr  zIlitellm.proxy.proxy_server.async_data_generator(): Exception occured - {}rs  ru  rv  r`   rV   rw  r  r#  rx  ry  r  )shieldaclosez7async_data_generator: error closing response stream: %s) r}   re  r  r  'async_post_call_streaming_iterator_hookrz  r  rK   rL   rg  get_response_stringr  r   r{  r  r@  rp  r  ru   r|  r'  rz  r?   r  r  rF  r&  anyioCancelScoper  r  BaseException)ri  r  rp  error_messager  r  _str_so_farrn  response_strr  r~  r  r  r  s                 rg   async_data_generatorr    s     12`'+&O%'
# !& ,TT/% U 
 !	, !	,% ,JJ"3!*5;4	 K  E %-1D!EF&::N|++I,G)&;	,(E( %+--4t-TE3'E,<,<X,F %,ugT**
 $|nD))N d+ 	x*"//+++	 	]!	,4  ,s1vhd+++,A
P   ,&&W^^A	

  66/ % 7 
 	
 	

 	""+A3  /A  B	
 a'G12AI
 AI(Ay)4FF+!Wf-M3/	
 Wo.E.E.G$HI~&d+++A ,R ,$ (..Q 		 	Ud+ 	x*"//+++$ (..Q 		 	 	s?  M/*F FEF!F ,E"-BF >	E$F M/0K >J3J0J3	M/F"F $	F
-F?F F

F 
J-AJ(!G$"C J("K, (J--K, 0J33	K<KK KK  K)%M/,M,M L+$L'
%L+*M +	M	4M	
M M	M 	M, M)%M,,M/c                     t        | ||      S )Nri  r  rp  )r  r  s      rg   select_data_generatorr    s      +! ri   r9  c                 
   | j                  di       }| j                  di       j                  dd       }	 d|v s|j                  d      r|j                  dd       }t        j                  |      }|S # t        $ r i cY S w xY w)Nr^  r  r9  azure
base_model)r  rg  get_model_inforp  )r9  r^  model_to_lookuplitellm_model_infos       rg   get_litellm_model_infor    s    <,Jii 0"599'4HOo%)E(nn\4@O$33OD!!  	s   =A4 4BBc                 6    t        j                  d| d          y )Nz$Backing off... this was attempt # %stries)r}   re  )r5  s    rg   
on_backoffr  
  s    EwwGWXri   c                 >   t        | t              xr; t        | dd       d uxr* t        | j                  t              xr d| j                  v  }t
        j                  d      du ry|r4t        j                  t        j                  dt	        |       d             |S )Nr`   z"Max parallel request limit reached1disable_retry_on_max_parallel_request_limit_errorTgiveup)eventr  )r  r?   r  r`   r  r  r  r}   re  r  rF  )r  r  s     rg   r  r    s    1n% 	>Ay$'t3	>qyy#&	> 1AII=	F 	PQ	 ""4::sSTv.V#WXMri   c                      e Zd Zedee   dedee   fd       Ze	de
dee   fd       Zedee   deeef   fd       Zede
d	ee   d
efd       Zedefd       Zeded
ed	eddfd       Zed        Zed        Zede
d	ededededefd       Zedefd       Zedede
ded	efd       Zedee   ded
edee   fd       Zed        Zed        Zy)r  r  r  r  c                 >    t                |j                  ||       y)z*Initialize logging and alerting on startup)r  r  N)r  startup_event)clsr  r  r  s       rg   r  z-ProxyStartupEvent._initialize_startup_logging#  s"     	''!5F 	( 	
ri   r  c                     ddl m} | j                  dd      }t        |t              r ||      }|r|t        d      yy)z
        Validates that when use_redis_transaction_buffer is enabled,
        a Redis cache is properly configured in litellm_settings.
        r   )r  use_redis_transaction_bufferFNa  `use_redis_transaction_buffer` is enabled in general_settings but no Redis cache is configured. This will cause spend updates to not be tracked. Add a Redis cache in litellm_settings:

litellm_settings:
  cache: true
  cache_params:
    type: redis
    url: os.environ/REDIS_URL
)litellm.secret_managers.mainr  r  r  r  r  )r  r  r  _use_redis_transaction_buffers       rg   r  z;ProxyStartupEvent._validate_redis_transaction_buffer_config2  s\     	=   !?G 	& 3S9,78U,V)(->-F2	 	 .G(ri   r  c                   K   ddl m} |j                  dd      }|r|j                  dd      st        j                  d       yt        j                  d|du d	|        |j                  ||
       d{   }|r5t        j                  d       t        j                  j                  |       yt        j                  d       y7 Qw)z1Initialize MCP semantic tool filter if configuredr   r  r  Nra  FzKSemantic tool filter not configured or not enabled, skipping initializationz.Initializing semantic tool filter: llm_router=z	, config=r  z$Semantic tool filter hook registeredzASemantic tool filter hook was configured but failed to initialize)
r  r  r  r}   re  r  rg  r  r  r|  )r  r  r  r  r  r  s         rg   r  z2ProxyStartupEvent._initialize_semantic_tool_filterO  s      	S%5%9%9&&
"
 *1K1O1Ou2
 !&&* ""<Zt=S<T U013	
 ,BB-! C 
 

  &&'MN,,AA$G !((S
s   A6C8C
9ACr]  r  c                 (   |j                  dd      ^|d   j                         D ]9  \  }}t        |t              s|j	                  d      s)t        |      |d   |<   ; t        di |d   }n
t               }t        j                  |||       y)zInitialize JWT auth on startuplitellm_jwtauthNr  )r]  r  r  r^  )	r  r  r  r  r@  r  r9   ri  r  )r  r  r]  r  r  r  r  s          rg   r  z&ProxyStartupEvent._initialize_jwt_authx  s      148D():;AAC K1a%!,,}*E=G]$%67:K .T0@AR0STO-/O&&'1+ 	' 	
ri   r  c                    t         j                  t        d      t        j                  t        dd|dg i i dt         j                  t         j                  dt         j                  t         j                  d             y)z Adds a global proxy budget to dbNzPbudget_duration not set on Proxy. budget_duration is required to use max_budget.userr   update_data)r  budget_duration)request_typer  r  durationrv  aliasesr~  r  r  r  
query_typeupdate_key_values)rg  r  rp  r  r  r   r  )r  r  s     rg   r  z)ProxyStartupEvent._add_proxy_budget_to_db  s|     ""*b 
 	"#!1"-- ' 7 7(")"4"4'.'>'>#	
ri   r  r.  Nc                    K   	 dj                  |      }t        |||       d{    y7 # t        $ r }t        j                  d|       Y d}~yd}~ww xY ww)zSWarm global spend cache once at startup to reduce impact of first wave of requests.r  )r  r  r]  Nz;Global spend cache warm-up at startup skipped or failed: %s)ru   r   rp  r}   re  )r  r  r  r]  r  r  s         rg   r  z*ProxyStartupEvent._warm_global_spend_cache  s`     
	"))*BCI=##5+  
  	 &&Mq 	s6   A". ,. A. 	AAAAAc                 <  K   t         j                  yt         j                  j                  d      xs g }|r[t        d |D              rHddlm} |D cg c]  }t        di | }} ||t        t        t                           d{    yyyc c}w 7 w)	z%Update the default team member budgetNteamsc              3   <   K   | ]  }t        |t                y wrP  )r  r  )rM  r  s     rg   rO  zGProxyStartupEvent._update_default_team_member_budget.<locals>.<genexpr>  s     DT*T40Ds   r   )!update_default_team_member_budgetr  )r  r  r^  )
rg  default_internal_user_paramsr  r  7litellm.proxy.ui_crud_endpoints.proxy_setting_endpointsr  NewUserRequestTeamrF   r   rQ  )r  _teamsr  r  teams_pydantic_objs        rg   r  z4ProxyStartupEvent._update_default_team_member_budget  s      //75599'BHbcDVDD JP!P"4"<t"<!P!P3(NQ[\fQg<h   E6
 "Qs   ABB'&BBBc                 H  K   	 ddl }ddlm} t        yt        j                  j
                  j                  ddi       d{   }|r|j                  r|j                  }t        |t              r |j                  |      n
t        |      }|D ci c]  }||v r|||    }}|rCt        j                  |       t        j                  dt!        |j#                                      yyyy7 c c}w # t$        $ r }t        j&                  d|       Y d}~yd}~ww xY ww)	z
        Load persisted UI settings from the database and sync runtime flags
        into general_settings so they take effect immediately after startup.
        r   N)_RUNTIME_GENERAL_SETTINGS_FLAGSr{  ui_settingsr  z5Synced UI settings to general_settings on startup: %sz1UI settings sync on startup skipped or failed: %s)r  r  r  r]  r  litellm_uisettingsr  r  r  r  r  r  r  rJ  r}   rd  r  r  rp  re  )	r  r  r  r  rawr  r  flags_to_syncr  s	            rg   r  z7ProxyStartupEvent._sync_ui_settings_to_general_settings  s(    	 $+..AAMM]+ N  I Y22++1;C1Ejdjjo4PS9 =!K' {1~%! !
 !$++M:(--O]//12 ! 3y!  	 &&CQ 	s^   D"C6 D"/C6 C/AC6 C1%AC6 +D"/C6 1C6 6	D?DD"DD"r  r  r  c           	      
  K   ddl m} ddlm} t	        t
        t        t        dd |       id |       id      a|t        j                  dt        d||z
              z   }	|t        j                  dd	      z   }
|j                  d
d      du r6t        ||      }t        j                  |j                  d|	ddt               t        j                  t         d|
|t"        |gddt               |j                  dd      du r(ddlm} t)        j*                   ||t"        |             t-        dt.              xs t.        at.        dur|	 |j0                  j2                  j5                  ddi       d{   }|st7        |j8                  t:              rY|j8                  j                  d      }|du s#t7        |t<              r*|j?                         dk(  rdatA        jB                  d       t.        du rt        j                  tH        jJ                  dd||gddt               tH        jK                  ||       d{    t        j                  tH        jL                  dd|gd dt               tH        jM                  |!       d{    | jO                  t        |||"       d{    | jQ                  t        #       d{    |j                  d$      tS               }|j                  d%      }|r[dd&l*m+} 	 |jY                  |      }t        j                  |jZ                  ||gd'dt        (       tA        jB                  d)|        n`|j                  d+d,      }	 ta        |      }t        j                  |jZ                  d|t        j                  dd-      z   |gd'dt               tb        utd        ro	 dd/l3m4}  |||tb        0      }t        j                  |jj                  dtl        t        j                  dd      z   d1dt               tA        jB                  d2       tb        utd        ro	 dd5l7m8}  |||tb        0      }t        j                  |jr                  dtl        t        j                  dd      z   d6dt               tA        jB                  d7       t        ju                  d:       tA        jB                  d;t                y7 o# tD        $ r*}tA        jF                  dt=        |             Y d}~&d}~ww xY w7 7 7 t7 Y# t\        $ r tA        j^                  d*|        Y w xY w# t\        $ r tA        j^                  d.       Y w xY w# tD        $ r8}tA        jF                  d3|        tA        jF                  d4       Y d}~|d}~ww xY w# tD        $ r8}tA        jF                  d8|        tA        jF                  d9       Y d}~Ed}~ww xY ww)<z%Initializes scheduled background jobsr   )AsyncIOExecutor)MemoryJobStore)coalescer5  max_instancesrj   N)job_defaults	jobstores	executorsr         disable_reset_budgetF)r  r]  r9  reset_budget_jobT)r;  r{  r4  r5  update_spend_jobr:  r2  )_monitor_spend_logs_queue)r]  rk  r  STORE_MODEL_IN_DBr  r  r  r  rR  z<store_model_in_db=True loaded from DB, overriding config/envz,Failed to check DB for store_model_in_db: %sadd_deployment_jobr]  r  get_credentials_jobrx  )r=  r  r  r]  r=  r/  r0  r1  r.  r3  z'Spend log cleanup scheduled with cron: r6  r7  r8  rn   r<  )CheckBatchCost)r  r]  r  check_batch_cost_jobz+Batch cost check job scheduled successfullyz%Failed to setup batch cost checking: zSChecking batch cost for LiteLLM Managed Files is an Enterprise Feature. Skipping...)CheckResponsesCostcheck_responses_cost_jobz/Responses cost check job scheduled successfullyz)Failed to setup responses cost checking: zWChecking responses cost for LiteLLM Managed Files is an Enterprise Feature. Skipping...)pausedzrAPScheduler started with memory leak prevention settings: removed jitter, increased intervals, misfire_grace_time=);apscheduler.executors.asyncior  apscheduler.jobstores.memoryr  rl   r   r   r   r=  rq   rE  ro  r  r   rB  reset_budgetr   rk  litellm.proxy.utilsr  r  r  r  r  r  r  r  r  r   r  r  r  r}   rd  rp  re  r  rz  r@  _initialize_slack_alerting_jobs*_initialize_spend_tracking_background_jobsr   r@  r2  rA  rC  r  r  r   r  r   6litellm_enterprise.proxy.common_utils.check_batch_costr  check_batch_costr1  :litellm_enterprise.proxy.common_utils.check_responses_costr  check_responses_coststart)r  r  r]  r  r  r  r  r  r  budget_intervalbatch_writing_intervalbudget_reset_jobr  _db_gs_record_db_valr  rG  rH  r2  rI  rJ  rK  r  r  r  r  s                             rg   r  z6ProxyStartupEvent.initialize_scheduled_background_jobs  sH    ( 	B?$0&D!: !."23 ?, 
	( <fnn14UU?
 
 "6q!8L!L  6>%G-"3+ 
  --'%!%#A   	*!13DE!!= 	 		
  4e<EE )"/%5&7 /1BCXGX 	 D(]-F&3&6&6&E&E&P&P');< 'Q ' ! !,!--t2 ,77;;<OPG$"7C0W]]_5N,0),11Z $ ++#%67'!%#A  	 --+?P .   
 ,,#_(!%#A  	 ..].KKK11-/'	 2 
 	
 	
 <<y<QQQ  EFR / 1+//0QRLA#.#;#;L#IL%%)@@$+_2)-+I &  )--A,P &6%9%9;T&"':;M'N$%%)@@" 06>>!R3H H+_2)-+I &  !&A (6&7"/)($
 !!(998nnQ+, .%)'E " 	 %))*WX !&A ,>&7"/),(
 !!,AA8nnQ+, 2%)'E " 	 %))E$ 	u%!!GGeFfh	
c!  $**BCF ( L	
 	R. " (..I,X( " (..M8  $**-RSTRU+VW$**i B  $**?sC %**m s'  EX+S, :S);A9S, 4AXT"AXT% X4T(5XT+8XAT. X3AU  XA.U; ;XA.V? 63X)S, ,	T5TXTX%X(X+X.!UXUXU84X7U88X;	V<-V71X7V<<X?	X -W;5X;X  Xr=  c                   K   ddl m} ddlm} ddlm}  |        d{   r|j                  |       d{    |j                  |       d{    ddlm	} ddl
m}m}m}m}	  |        d{   r |       sx |	        d{   ri	  |        d{   }
|
rW ||
j                  d	      |
j                  d
      |
j                  d            }t         j"                  j%                  |       |j-                  |       d{    t         j.                  du rddlm} |j5                  |       ddlm}m} t=        |      }t)        j>                  d|        |du ri	 ddl m!} tD        E |tD              }t)        j>                  d| d       |jG                  |jH                  d|d       nt)        j*                  d       yyt)        j>                  d       y7 7 7 7 7 l7 _# t&        $ r!}t)        j*                  d|       Y d}~)d}~ww xY w7 # t&        $ r"}t)        j*                  d|        Y d}~yd}~ww xY ww)a+  
        Initialize the spend tracking and other background jobs
        1. CloudZero Background Job
        2. Focus Background Job
        3. Prometheus Background Job
        4. Key Rotation Background Job

        Args:
            scheduler: The scheduler to add the background jobs to
        r   )CloudZeroLogger)FocusLogger)is_cloudzero_setupNr  )VantageLogger)_get_vantage_settingsis_vantage_setupis_vantage_setup_in_configis_vantage_setup_in_dbapi_keyintegration_tokenbase_url)r  r  r  z5Failed to register VantageLogger from DB settings: %sTr  )+LITELLM_KEY_ROTATION_CHECK_INTERVAL_SECONDSLITELLM_KEY_ROTATION_ENABLEDzkey_rotation_enabled: )KeyRotationManagerz,Key rotation background job scheduled every z, seconds (LITELLM_KEY_ROTATION_ENABLED=true)r9  key_rotation_job)r;  r{  z4Key rotation enabled but prisma_client not availablez"Failed to setup key rotation job: zGKey rotation disabled (set LITELLM_KEY_ROTATION_ENABLED=true to enable))%(litellm.integrations.cloudzero.cloudzeror  'litellm.integrations.focus.focus_loggerr  0litellm.proxy.spend_tracking.cloudzero_endpointsr  init_cloudzero_background_job init_focus_export_background_job+litellm.integrations.vantage.vantage_loggerr  .litellm.proxy.spend_tracking.vantage_endpointsr   r  r  r  r  rg  r  r  rp  r}   r|  init_vantage_background_job$prometheus_initialize_budget_metricsrR  r  "initialize_budget_metrics_cron_joblitellm.constantsr  r  r  re  /litellm.proxy.common_utils.key_rotation_managerr	  r]  rB  process_rotations)r  r=  r  r  r  r  r   r  r  r  db_settingsvantage_loggerr  r  r  r  key_rotation_enabledr	  key_rotation_managers                      rg   r  z<ProxyStartupEvent._initialize_spend_tracking_background_jobs  sa    " 	MGW#%%%!??)?TTT
 ::Y:OOO
 	N	
 	
 "### ./:P:R4R4R(=(?"?K")6$/OOI$>.9oo>Q.R%0__Z%@*
  88MM*  ;;i;PPP
 774?H??)?T	

 0;;W/X""%;<P;Q#RS4'W !,+=m+L((..FGrFs  t`  a %%,>>" K-	 &  )00N !&&Yk &T
 	P $ 5S"? ! (00OQR  QV  W$,,/QRSQT-UVVWs   IG*IG-IG0 I4G35I
G6I
G< G9AG< 8IH)AI,A&H, I-I0I3I6I9G< <	H&H!I!H&&I,	I5IIIIc                   K   |s|j                   j                  [|Wt        d       |j                  dd      xs d}t	        |dd       }|d   j                         dk7  rt        d      |j                  |j                   j                  d|t        j                         t        d	t        j                  d
d      z         z   |gddt               |j                  |j                   j                  dddd       t!        j"                  d      r_d
dlm} |j                  |j                   j(                  dt*        d
 |d      dd       |j                   j)                          d{    yyyyy7 	w)z<Initialize Slack alerting background jobs for spend reports.Nz3Alerting: Initializing Weekly/Monthly Spend Reportsspend_report_frequency7dr^  zBspend_report_frequency must be specified in days, e.g., '1d', '7d'r9  
   r   i,  )r;  weekly_spend_report_jobT)daysnext_run_timerx  r{  r4  r5  cronr  monthly_spend_report_job)dayr{  r4  PROMETHEUS_URL)ZoneInfozAmerica/Los_Angelesprometheus_fallback_stats_job)hourminuter   r{  r4  )r(  r  rt   r  r(  r  r  rB  send_weekly_spend_reportr   nowr   rq   rE  r   send_monthly_spend_reportr  r  zoneinfor(  #send_fallback_stats_from_prometheusr   )r  r=  r  r  r]  r  r"  r(  s           rg   r  z1ProxyStartupEvent._initialize_slack_alerting_jobs  s     )!99BBN)GH $$%=tDL # -cr23D%b)//1S8 X  !99RR&llnB3)?$?@A,-,!%#A  
 !99SS-!%   yy)*-!!%==aaB%&;<6%) "  (??cceee +C * O *^ fs   E.E<0E:1
E<r  c                 t  K   	 d}|	 t        ||      }	 |j                          d{    t        |d      r8t        |j                  d	      r"|j                  j                          d{    t        j                  |j                                t        j                  |j                                t        d
d      dur|j                          d{    t        |d      r|j                          d{    |S # t        $ r}|d}~ww xY w7 # t        $ r`}dt        |      v sdt        |      v r?t	        j
                  d       t	        j
                  d       t	        j
                  d       |d}~ww xY w7 7 7 # t        $ r}t!        j"                  |       Y d}~yd}~ww xY ww)zQ
        - Sets up prisma client
        - Adds necessary views to proxy
        N)r  r  P3018P3009z#CRITICAL: DATABASE MIGRATION FAILEDz$Your database is in a 'dirty' state.z<FIX: Run 'prisma migrate resolve --applied <migration_name>'r  start_token_refresh_task&DISABLE_PRISMA_HEALTH_CHECK_ON_STARTUPFTstart_db_health_watchdog_task)r   rp  connectr  r}   re  r  r  r4  r  r  check_view_exists(_set_spend_logs_row_count_in_proxy_stater  health_checkr6  r   handle_db_exception)r  r  r  r  r]  r  s         rg   r  z&ProxyStartupEvent._setup_prisma_client  s    6	48M'$0%1EV%M'//111" =$/G!$$&@5 (**CCEEE ##!335 ##!JJL $$LeT  (44666=*IJ'EEGGG  Y ! G 2  #a&(Gs1v,=,22A -22B -22Z G& F  7 H 	$88;	s   F8F D D DD ?F .F/A+F F	#F >F?F F8	DDDF D 	F#AE>>FF 	F F 	F5F0+F80F55F8c                     ddl m}m}  |       rddl}|j	                  dd        |       r3ddlm}  |       }|j                          t        j                  d       yy)	z
        Initialize dd tracer - if `USE_DDTRACE=true` in .env

        DD tracer is used to trace Python applications.
        Doc: https://docs.datadoghq.com/tracing/trace_collection/automatic_instrumentation/dd_libraries/python/
        r   )_should_use_dd_profiler_should_use_dd_tracerNTF)r[  openai)ProfilerzDatadog Profiler started......)
%litellm.litellm_core_utils.dd_tracingr=  r>  ddtrace	patch_allddtrace.profilingr@  r  r}   re  )r  r=  r>  rB  r@  profs         rg   r  z!ProxyStartupEvent._init_dd_tracer   sR    	

 !"d59"$2:DJJL &&'GH %ri   c                    t        dd      st        j                  d       y	 ddl}t	        j
                  d      }|st        d      t	        j
                  d      }|st        d	      i }t	        j
                  d
      xs t	        j
                  d      }|r||d<   t	        j
                  d      }|||r|ndd}|	 t        t        |            |d<    |j                  di | d| d| d| d}d|v r|d|d    z  }t        j                  |       y# t        t        f$ r t        d|      w xY w# t        $ r t        j                  d       Y yw xY w)a  
        Optional continuous profiling via Grafana Pyroscope.

        Off by default. Enable with LITELLM_ENABLE_PYROSCOPE=true.
        Requires: pip install pyroscope-io (optional dependency).
        When enabled, PYROSCOPE_SERVER_ADDRESS and PYROSCOPE_APP_NAME are required (no defaults).
        Optional: PYROSCOPE_SAMPLE_RATE (parsed as integer) to set the sample rate.
        LITELLM_ENABLE_PYROSCOPEFzWLiteLLM: Pyroscope profiling is disabled (set LITELLM_ENABLE_PYROSCOPE=true to enable).Nr   PYROSCOPE_APP_NAMEzsLITELLM_ENABLE_PYROSCOPE is true but PYROSCOPE_APP_NAME is not set. Set PYROSCOPE_APP_NAME when enabling Pyroscope.PYROSCOPE_SERVER_ADDRESSzLITELLM_ENABLE_PYROSCOPE is true but PYROSCOPE_SERVER_ADDRESS is not set. Set PYROSCOPE_SERVER_ADDRESS when enabling Pyroscope.OTEL_ENVIRONMENT_NAMELITELLM_DEPLOYMENT_ENVIRONMENTenvironmentPYROSCOPE_SAMPLE_RATE)app_nameserver_addressr  sample_ratez-PYROSCOPE_SAMPLE_RATE must be a number, got: z/LiteLLM: Pyroscope profiling started (app_name=z, server_address=zA). View CPU profiles at the Pyroscope UI and select application 'z'.z sample_rate=zLiteLLM: LITELLM_ENABLE_PYROSCOPE is set but the 'pyroscope-io' package is not installed. Pyroscope profiling will not run. Install with: pip install pyroscope-ior^  )r  r}   re  	pyroscoper  r  r  r(  r  r  	configurerd  ImportErrorr|  )	r  rQ  rN  rO  r  env_namesample_rate_envconfigure_kwargsmsgs	            rg   r  z!ProxyStartupEvent._init_pyroscope  s    95A &&i 0	yy!56H F   YY'ABN! L  Dyy!89 RYY0>H &.]# ii(?@O$"0 $$ 
 *69%:P6Q$]3  I3"23A(K\]k\l mQQYPZZ\^   00'7'F&GHH %%c* #I. $G*-/   	 (([	s+   BD> D AD> D;;D> >EE)r^   r  r  classmethodr   r{   r   r   r  rD  r  r  r	   r  r   r  r   r   r  r  r  r  r  r(  r  rl   r  r  r  r  r  r^  ri   rg   r  r  "  sv   
V$
 (
 $J/	
 
 #J/ 8 &V$& sCx.& &P 

  -
 &	
 
( 
 
 
8 "% & $	
 
 &    " "H ]
]
 $]
 ,/	]

 ,/]
 "]
 (]
 ]
~ k(k kZ 8f#8f 8f (	8f
 $8f 8ft @sm@ (@ &	@
 
,	@ @D I I0 > >ri   r  z
/v1/modelszmodel management)dependenciesr  z/modelsreturn_wildcard_routesinclude_model_access_groupsonly_model_access_groupsinclude_metadatafallback_typescopec                 4  K   ddl m} ddlm}	m}
 ||dk7  rt        dd|       d	}|dk(  r  || t        t        t        
       d{   }|rt        g }i }n(t        j                         }t        j                         }|r.t        t        |t        |j                               z               }ddlm}  |g g |dd	|xs d	t        ||xs d	|xs d	
      }g }|D ](  } |	|d|xs d	|t              }|j#                  |       * t%        |d      S  |
| t        t&        t(        t        t        ||xs d	|xs d	|xs d	t               d{   }g }|D ](  } |	|d|xs d	|t              }|j#                  |       * t%        |d      S 7 I7 Cw)a  
    Use `/model/info` - to get detailed model information, example - pricing, mode, etc.

    This is just for compatibility with openai projects like aider.

    Query Parameters:
    - include_metadata: Include additional metadata in the response with fallback information
    - fallback_type: Type of fallbacks to include ("general", "context_window", "content_policy")
                    Defaults to "general" when include_metadata=true
    - scope: Optional scope parameter. Currently only accepts "expand".
             When scope=expand is passed, proxy admins, team admins, and org admins
             will receive all proxy models as if they are a proxy admin.
    r   )r   )create_model_info_responseget_available_models_for_userNexpand  zIInvalid scope parameter. Only 'expand' is currently supported. Received: r  Fr  r]  r  r  )r   )

key_modelsteam_modelsproxy_model_listrY  infer_model_from_keysrZ  r  model_access_groupsr[  r\  r?  r  r  r]  r^  r  r  )r  objectr  r  r  rY  r]  r  r  r[  r\  rZ  r  )/litellm.proxy.management_endpoints.common_utilsr   r  ra  rb  r'  r]  r  r  r  get_model_namesget_model_access_groupsr  r&  r  litellm.proxy.auth.model_checksr   r  r  r  rY  )r  rZ  r  r[  r\  r]  r^  r_  r   ra  rb  should_expand_scoperh  rj  r   
all_models
model_datar9  r^  s                      rg   r4  r4  \  s    > Uh.^_d^ef
 	
  $>/'1/	%
 
 !"$)99;","D"D"F '#$t,?,D,D,F'GGH 
 	L,-"'#9#BU! 3(C(Lu%=%F

 
 	*E3!!1!:U+%J j)	* 
 	
 5+)#+$?$H5!9!BU5>- J J &/-6'!

 	*%&  i
ts&   AF
FDFFAFFz/v1/models/{model_id}z/models/{model_id}r  c                   K   ddl m}m}m}  ||t        t
        t        t        t        ddddt               d{   } || |       t        t        dd	      t        j                  |       }|t        d
d|  d	      t        j                  |j                  j                        \  }}}} || |ddt              S 7 w)ak  
    Retrieve information about a specific model accessible to your API key.

    Returns model details only if the model is available to your API key/team.
    Returns 404 if the model doesn't exist or is not accessible.

    Follows OpenAI API specification for individual model retrieval.
    https://platform.openai.com/docs/api-reference/models/retrieve
    r   )ra  rb  validate_model_accessNFrm  )r  available_modelsrx  zRouter not initializedr    zModel 'z#' not found in router configurationr  rk  )r  ra  rb  rv  r  r  rY  r]  r  r  r'  "get_deployment_by_model_group_namerg  get_llm_providerr  r9  )	r  r  ra  rb  rv  rs  r  r  r  s	            rg   r^  r^    s     2  5+)#+$)!&$- J 8jI 4LMM>>xHJXJ&IJ
 	
  00z7P7P7V7VWAxA & As   9CCB
Cz/v1/chat/completionszchat/completionsz/chat/completionsz&/engines/{model:path}/chat/completionsz1/openai/deployments/{model:path}/chat/completions   r  zSuccessful response)rY  r  r  fastapi_responsec                 l  K   t        |        d{   }||j                  d      i |d<   t        |d      r|j                  |j                  |d   d<   t        |d      r|j                  |j                  |d   d<   t        |d      r|j
                  |j
                  |d   d	<   t        |d
      r|j                  |j                  |d   d
<   t        |      }	 |j                  | ||dt        t        t        t        t        |t        t        t         t"        t$        t&               d{   }t)        |t*              rt-        |d      S |S 7 F7 &# t.        $ rG}|j0                  }t        j3                  |||       d{  7   t5        j6                         }	|j8                  |	_        |j:                  |	j<                  d   j:                  _        d|	j<                  d   _         |j                  dd      ||d   du rut4        jB                  jE                  |	d      }
t5        jF                  |
|j8                  d|j                  dd            }t        |||      }tI        |dd      cY d}~S t5        jJ                  ddd      }||	_&        |	cY d}~S d}~wtN        $ rN}|j0                  }t        j3                  |||       d{  7   t5        j6                         }	|j:                  |	j<                  d   j:                  _        |j                  dd      |d   du rt4        jB                  jE                  |	d      }
t5        jF                  |
|j                  dd      d|j                  dd            }t        |||      }tI        |dt        |d      r|jP                  ntR        jT                        cY d}~S t5        jJ                  ddd      }||	_&        |	cY d}~S d}~wtV        $ r&}|jY                  ||t                d{  7  d}~ww xY ww)!a  

    Follows the exact same API spec as `OpenAI's Chat API https://platform.openai.com/docs/api-reference/chat`

    ```bash
    curl -X POST http://localhost:4000/v1/chat/completions 
    -H "Content-Type: application/json" 
    -H "Authorization: Bearer sk-1234" 
    -d '{
        "model": "gpt-4o",
        "messages": [
            {
                "role": "user",
                "content": "Hello!"
            }
        ]
    }'
    ```

    r   Nmetadatar  user_api_key_user_idr  user_api_key_team_idorg_iduser_api_key_org_idagent_idr  acompletionr   r|  r  
route_typer  r  r  r  r  r9  rY  r`  ra  user_max_tokensr_  r!  T)r  rs  r   content_filterstreammodel_responseconvert_to_deltacached_responselitellm_logging_obj)completion_streamr9  custom_llm_providerlogging_objr  text/event-streamr{  
media_typer#  prompt_tokenscompletion_tokenstotal_tokensr9  r  r#  )r  r  r  )-r   r  r  r  r  r  r  r   base_process_llm_requestr  r  r  r  r  rY  r`  ra  r  r_  r!  r  r   r   r   rp  r|  rg  rK   r9  r`   choicesr$  finish_reasonutilsModelResponseIteratorCustomStreamWrapperr:  Usageusager   r#  r0  HTTP_400_BAD_REQUESTrp  _handle_llm_api_exception)r   r|  r9  r  r  base_llm_response_processorr  r  _data_chat_response	_iterator_streaming_responseselected_data_generator_usages                 rg   chat_completionr  0  s*    h $G44D$88J'!D%y1!))57H7P7PD34%y1!))57H7P7PD34%x0!((46G6N6ND23%z2!**6+<+E+EDZ("?T"Jg
2KK-/$/!-%"7!-!5+'! L 
 
$ fi(3F$OOM_ 54
, # $66/  7 
 	
 	

 !..0 ww45IIq!))12Bq!/88Hd#/DNd4J;;- < I #*"="="+gg$5 HH%:DA	# '<,"3"'# %'. 
 Q!RST% %66/  7 
 	
 	

 !..045IIq!))188Hd#/DNd4J;;- < I #*"="="+hhw+$5 HH%:DA	# '<,"3"'# %'. q-0 MM44  Q!RST% 
/II// J 
 
 
 	

s   P4ECP4$AE 4E5 E P4E P4E 
P1''J)FC.J)=P1>P4 J)#P1$P4)P16'O?K C5O?P1P4 O?9P1:P4?P1P,&P)'P,,P11P4z/v1/completionscompletionsz/completionsz!/engines/{model:path}/completionsz,/openai/deployments/{model:path}/completionsc                 	  K   i }	 t        |        d{   }||j                  d      i |d<   t        |d      r|j                  |j                  |d   d<   t        |d      r|j                  |j                  |d   d<   t        |d      r|j
                  |j
                  |d   d	<   t        |d
      r|j                  |j                  |d   d
<   t        |      }|j                  | ||dt        t        t        t        t        |t        t        t         t"        t$        t&               d{   S 7 &7 # t(        $ r}|j*                  }t        j-                  |||       d{  7   |j                  dd      |d   du rt/        j0                         }t3        |j4                  d   d|j6                         |j8                  |_        t/        j:                  ddd      }	t3        |d|	       t.        j<                  j?                  |d      }
t/        j@                  |
|j8                        }t        |||      }tC        |dd      cY d}~S t/        jD                         }|j6                  |j4                  d   _#        |j8                  |_        t/        j:                  ddd      }	|	|_$        |cY d}~S d}~wtJ        $ ro}|j*                  }t        j-                  |||       d{  7   |j                  dd      |d   du rt/        j0                         }t/        j:                  ddd      }	|	|_$        |j6                  |j4                  d   j6                  _&        t.        j<                  j?                  |d      }
t/        j@                  |
|j                  dd            }t        |||      }tC        |di t        |d      r|jN                  ntP        jR                        cY d}~S t/        jD                         }|j6                  |j4                  d   _#        |cY d}~S d}~wtT        $ r}t        j-                  |||       d{  7   tW        jX                  dj[                  t]        |                   t]        |       }t_        ta        |d |      ta        |d!d"      ta        |d#d"      ta        |d$d      ta        |dd%      &      d}~ww xY ww)'a  
    Follows the exact same API spec as `OpenAI's Completions API https://platform.openai.com/docs/api-reference/completions`

    ```bash
    curl -X POST http://localhost:4000/v1/completions 
    -H "Content-Type: application/json" 
    -H "Authorization: Bearer sk-1234" 
    -d '{
        "model": "gpt-3.5-turbo-instruct",
        "prompt": "Once upon a time",
        "max_tokens": 50,
        "temperature": 0.7
    }'
    ```
    r~  Nr  r  r  r  r  r  r  r  r  atext_completionr  rs  r  Tr   textr  r  r  )r  r9  r  r  r{  r  r9  r  r#  )r  r%  r#  z?litellm.proxy.proxy_server.completion(): Exception occured - {}r`   rV   rw  r  r'  rx  r`   rV   r  openai_coder'  )1r   r  r  r  r  r  r  r   r  r  r  r  r  r  rY  r`  ra  r  r_  r!  r   rp  r|  rg  rK   rV  r  r`   r9  r  r  r  TextCompletionStreamWrapperr:  rM   r  r  r   r$  r#  r0  r  rp  r}   r  ru   r  r?   r  )r   r|  r9  r  r  r  r  r  _text_responser  r  r  r  	_responser  r  s                   rg   
completionr    s    R D[
'88(xx
#+#%Z )95%--9;L;T;TZ !78)95%--9;L;T;TZ !78)84%,,8:K:R:RZ !67):6%..:/@/I/IZ ,&C&N#0II-/)/!-%"7!-!5+'! J 
 
 	
3 92
$ # 266/  7 
 	
 	
 99Xt$0U8_5L$224NN**1-vqyyA#$77N ]]"#F NGV4;;- < I #*"E"E"+gg#
 '<,"3"'# %'.   668I()		Ia %ggIO]]"#F
 %IO +66/  7 
 	
 	

 99Xt$0U8_5L$224N]]"#F
 $*N 89		N""1%--5;;- < I #*"E"E"+ii,#
 '<,"3!'# %'. q-0 MM44	 	  668I()		Ia % 
66/ATX 7 
 	
 	
 	&&MTTA	

 1vh	Ay)4FF+!Wf-640M3/
 	

s   S6E  D;D E  6D>7E  :S6;E  >E   
S3
'K
1E42C)K
S3S6!A#K
S3S6
S3'Q>L?DQS3S63Q;S3<S6S3S.(Q+)BS..S33S6z/v1/embeddings
embeddings)rY  response_classr  z/embeddingsz /engines/{model:path}/embeddingsz+/openai/deployments/{model:path}/embeddingsc                 t  K   i }	 t        |        d{   }t        t        j                  ng }d|v rt        |d   t              rt        |d         dkD  rt        |d   d   t              rt        |d   d   d   t              rt        |j                  d      |v rt        j                  |d         }||j                  di       xs i }|j                  dd      t        j                  v xs t        fd	t        D              }|s7g }	|d   D ](  }
|	j                  t        j                  d
|
             * |	|d<   ||j                  d      i |d<   t        |d      r|j                   |j                   |d   d<   t        |d      r|j"                  |j"                  |d   d<   t        |d      r|j$                  |j$                  |d   d<   t        |d      r|j&                  |j&                  |d   d<   t)        |      }|j+                  | ||dt,        t        t.        t0        t2        |t4        t6        t8        t:        t<        t>               d{   }|S 7 Z7 	# t@        $ r7}t)        |      }|jC                  ||t,        t>               d{  7  d}~ww xY ww)a  
    Follows the exact same API spec as `OpenAI's Embeddings API https://platform.openai.com/docs/api-reference/embeddings`

    ```bash
    curl -X POST http://localhost:4000/v1/embeddings 
    -H "Content-Type: application/json" 
    -H "Authorization: Bearer sk-1234" 
    -d '{
        "model": "text-embedding-ada-002",
        "input": "The quick brown fox jumps over the lazy dog"
    }'
    ```

r~  Ninputr   r9  )model_group_namer  r  c              3   @   K   | ]  }j                  |        y wrP  )r@  )rM  r  litellm_models     rg   rO  zembeddings.<locals>.<genexpr>  s&      e$ &00:es   zgpt-3.5-turbo)r9  tokensr  r  r  r  r  r  r  r  r  
aembeddingr  )r  r  r  r!  )"r   r  model_namesr  r  rn  r(  r  ry  rg  open_ai_embedding_modelsr1  r"   r  decoder  r  r  r  r  r   r  r  r  r  r  rY  r`  ra  r  r_  r!  rp  r  )r   r|  r9  r  r  router_model_namesr  r  supports_token_arrays
input_listir  ri  r  r  s                 @rg   r  r    s    ` D]
'88 8B7MZ33SUtO4=$/DM"Q&4=+T24=+A.4 %$((7*;?Q*Q'JJ%)'] K 
 )%/^^4Db%I%ORN$2$6$6w$CM,9W=]=],] -ad e(de b) 1%'
!%g A&-- '_Q O )3W(xx
#+#%Z )95%--9;L;T;TZ !78)95%--9;L;T;TZ !78)84%,,8:K:R:RZ !67):6%..:/@/I/IZ , 'D&N# 5MM-/#/!-%"7!-!5+'! N 
 
& e 9~
(  
&C&N#/II//	 J 
 
 
 	

sW   J8I5 I0II5 )I3*I5 /J80I5 3I5 5	J5>,J0*J-+J00J55J8z/v1/moderationsmoderationsz/moderationsc                   K   i }	 | j                          d{   }t        j                  |      }t        || t        |t
        t               d{   }t        j                  dd      xs t        xs |j                  d      |d<   t        r	t        |d<   t        j                  ||d       d{   }t        j                          t        |dt        t               d{   }| d{   }t        j                  t        j!                  |j                  d	d
      d             t#        |di       xs i }|j                  dd      xs d
}|j                  dd      xs d
}	|j                  dd      xs d
}
|j$                  j'                  t)        j*                  |||	|
t
        t#        |dd
      ||             |S 7 7 |7 7 7 # t,        $ r}t        j/                  |||       d{  7   t1        j2                  dj5                  t7        |                   t9        |t:              rRt=        t#        |dt7        |            t#        |dd      t#        |dd      t#        |dt>        j@                              t7        |       }t=        t#        |d|      t#        |dd      t#        |dd      t#        |dd            d}~ww xY ww)a~  
    The moderations endpoint is a tool you can use to check whether content complies with an LLM Providers policies.
    Quick Start
    ```
    curl --location 'http://0.0.0.0:4000/moderations'     --header 'Content-Type: application/json'     --header 'Authorization: Bearer sk-1234'     --data '{"input": "Sample text goes here", "model": "text-moderation-stable"}'
    ```
    Nr  r   r  r  r!  r  moderation_modelr9  
moderationr  r  	call_typeamoderationr  r  r  rY  r  r  r  r  r0  _hidden_paramsr  r  r:  allowed_model_regionr  r  r  r:  r!  model_regionrp  hidden_paramsrs  z@litellm.proxy.proxy_server.moderations(): Exception occured - {}r`   rV   rw  r  r#  ry  rx  )!bodyorjsonr  r   r  r!  r  r  rY  r  pre_call_hookr  r   r  r  r  update_request_statusr  r%  rJ  r   get_custom_headersrp  r|  r}   r  ru   r  r  r'  r?   r0  r  )r   r|  r  r  r  llm_callri  r  r  r  r:  r  r  s                rg   r  r  @  s    8 DY\\^#||D! 1-/%
 
   !3T: !!xx  	W
 &DM '44/dl 5 
 
 			 '$!!	
 
 "> 	33 $):B ?	 4 	
  *:B?E2 $$Z6<"!%%k48>B	 $$Z6<"  '')<<"3!#!$%68NPRS!+		
  $
$

 ":  66/ATX 7 
 	
 	
 	&&NUUA	

 a' 9c!f5Q/a&1Qv/J/JK	  q6(I 9i8Q/a&1Qs3	 %s   K!G G9G GA"G 6G72G )G*	G 3G4CG K!G G G G G 	K"K=H >CKKK!r  c                t   K   | j                  t               d {   }|2 3 d {   }| 7 7 6 y w)N)
chunk_size)aiter_bytesr   )r  
_generatorrn  s      rg   _audio_speech_chunk_generatorr    sB      !,,8O,PPJ!  e Qzs$   828646868z/v1/audio/speechaudioz/audio/speechc                 R  K   i }	 | j                          d{   }t        j                  |      }t        || t        |t
        t               d{   }|j                  dd      |j                  |j                  |d<   t        r	t        |d<   t        j                  ||d       d{   }t        |dt        t               d{   }| d{   }t        j                  t        j!                  |j                  dd	      d
             t#        |di       xs i }|j                  dd      xs d	}|j                  dd      xs d	}	|j                  dd      xs d	}
|j                  dd      xs d	}|j                  dd      xs d	}t%        j&                  |||	|
t
        |t#        |dd	      d|||      }d}|j                  dd	      }|r|j)                         }d|v r
d|v sd|v rd}t+        t-        |      ||      S 7 7 7 g7 K7 D# t.        $ r|}t        j1                  |||       d{  7   t3        j4                  dj7                  t9        |                   t3        j:                  t=        j>                                |d}~ww xY ww)z`
    Same params as:

    https://platform.openai.com/docs/api-reference/audio/createSpeech
    Nr  r  r9  aspeechr  r  r  r  r  r  r  r  r  r:  r  r  )r  r  r  r:  r!  r  r  !fastest_response_batch_completioncall_idrp  r  z
audio/mpeggeminittszpreview-ttsz	audio/wav)r  r%  rs  zAlitellm.proxy.proxy_server.audio_speech(): Exception occured - {}) r  r  r  r   r  r!  r  r  r  rY  r  r  r   r  r  r  r  r  r   r  r  r:  r  rp  r|  r}   r  ru   r  re  r  r  )r   r|  r  r  r  r  ri  r  r  r  r:  r  r  custom_headersr  request_modelrequest_model_lowerr  s                     rg   audio_speechr    s    * D^\\^#||D! 1-/%
 
 88FD!).?.G.G.S,44DL&DM '44/di 5 
 

 ' !!	
 
 "> 	33 $):B ?	 4 	
  *:B?E2 $$Z6<"!%%k48>B	 $$Z6<"%))/4@FB'++,=tDJ6II/' !24JBO.2#'
 "
"-"/"5"5"7..,,AT0T    !)(3!"
 	
U $
 


 "b  66/  7 
 	
 	

 	""OVVA	

 	""9#7#7#9:s   J'H H9H HAH /H0H H	H HD6H J'H H H H H 	J$(JIAJJ$$J'z/v1/audio/transcriptionsz/audio/transcriptions.rd   c                 $	  K   i }	 t        |        d{   }|j                         D ci c]  \  }}|dk7  s|| }}}t        || t        |t        t
               d{   }|j                  dd      |j                  |j                  |d<   t        j                  dd      xs t        xs |j                  dd      |d<   t        r	t        |d<   t        t        j                  ng }|j                  t        dt        j                  dd	      t        |||
       |j!                          d{   }	t#        j$                  |	      }
|j                  |
_        |
|d<   	 t(        j+                  ||d       d{   }t-        |dt        t               d{   }| d{   }	 |
j1                          t3        j4                  t(        j7                  |j                  dd      d             t9        |di       xs i }|j                  dd      xs d}|j                  dd      xs d}|j                  dd      xs d}|j                  dd      xs d}|j                  dd      xs d}|j                  di       xs i }|j:                  j=                  t?        j@                  d'||||t        |t9        |dd      |||d
|       t(        jC                  |||tE        | j:                               d{   }|r|j:                  j=                  |       |S 7 c c}}w 7 7 7 7 7 # t.        $ r}|d}~ww xY w# |
j1                          w xY w7 c# t.        $ r}t(        jG                  |||       d{  7   tI        jJ                  djM                  tO        |                   tQ        |tR              r\t        t9        |dtO        |jT                              t9        |dd       t9        |d!d       t9        |d"t        j                        #      tO        |       }t        t9        |d|      t9        |dd       t9        |d!d       t9        |d$d      t9        |d"d%      &      d}~ww xY ww)(zq
    Same params as:

    https://platform.openai.com/docs/api-reference/audio/createTranscription?lang=curl
    Nrd   r  r  r  r9  z.File name is None. Please check your file namebad_request)r`   r'  rV   r  )rp  rd   r  transcriptionr  atranscriptionr  r  r  r  r  r  r  r  r:  r  additional_headersr  )
r  r  r  r:  r!  r  r  r  rp  r  )r  r  ri  request_headersrs  zHlitellm.proxy.proxy_server.audio_transcription(): Exception occured - {}r`   rV   rw  r  r#  ry  r'  rx  r  r^  )+r   r  r   r  r!  r  r  r  rY  r  r  rb   r?   r0  r  r   readioBytesIOr  r  r  r   rp  rj  r  r  r  r  r%  rJ  r   r  post_call_response_headers_hookr  r|  r}   r  ru   r  r  r'  r  )r   r|  rd   r  r  	form_datar  r  r  file_contentfile_objectr  ri  r  r  r  r  r:  r  r  r  callback_headersr  s                          rg   audio_transcriptionsr  <  s    , DH'00	-6__->PzsE#-U
PP 1-/%
 
 88FD!).?.G.G.S,44DL   !3T: ''xx& 	W
 &DM7A7MZ33SU==  H00"	  	$1	
 "YY[(jj.=="V	 *88"3) 9  D ++%%	 H &~H  	33 $):B ?	 4 	
  *:B?E2 $$Z6<"!%%k48>B	 $$Z6<"%))/4@FB'++,=tDJ#0#4#45I2#N#TRT  '')<< "3!#!+$%68NPRS'!+ %	
" "3!R!R/ 1	 "S "
 
 $$++,<=[ 1P
J ) & 	G	 F
  66/ATX 7 
 	
 	
 	&&V]]A	

 a' 9c!((m<Q/a&1Qv/J/JK	  q6(I 9i8Q/a&1#Avt4Qs3 %s   RM1 L/M1 L2L2#M1 "L8#CM1 :L;;/M1 +M L>M %M&	M /M0M 5EM1 M/"M1 .R/M1 2M1 ;M1 >M M M 	MMMM M,,M1 1
R;RNC1RRRz/vertex_ai/livezGOptional model name, used to determine Vertex region for global models.)r  zCOverride the Vertex AI project id used for the upstream connection.z;Override the Vertex AI region (for example, 'us-central1').	websocketvertex_projectvertex_locationc                 >   K   t        | ||||       d{   S 7 w)z
    Vertex AI Live API WebSocket Pass-through Endpoint

    This endpoint delegates to the WebSocket function defined in llm_passthrough_endpoints.py
    r  r9  r  r  r  Nr   r  s        rg   #vertex_ai_live_passthrough_endpointr     s.     , 6%'+   s   )maxsizeintentc                 L    d| fg}||j                  d|f       t        |      S )z
    Build a hashable representation of the realtime query params so we can cache
    the repetitive model/intent combinations.
    r9  r  )r  tuple)r9  r  paramss      rg   _realtime_query_params_templater    s2     '.u%5$6Fx()=ri   z	/realtimez'The intent of the websocket connection.zAComma-separated list of guardrail names to apply to this request.r  c                 X  K   | j                   j                  d      xs dj                  d      D cg c]"  }|j                         r|j                         $ }}i }|r|d   |d<    | j                  di | d {    t        t        t        t        |                  }| |d}	|rA|j                  d      D 
cg c]#  }
|
j                         s|
j                         % c}
|	d<   t        | j                  j                  d      xs g       }t        j                         }||d<   t        |	      }| j                  |_        fd
}||_        t#        |	      }	 |j%                  |t&        |t(        t*        t,        t.        t0        t2        t4        t6        d       d {   \  }	}	 ||	d<   tI        |	dtJ        t.               d {   }| d {    y c c}w 7 jc c}
w 7 D# t8        $ r}t;        j<                  d       	 | j?                  tA        jB                  ddtE        |      dd             d {  7   n# t8        $ r Y nw xY w| jG                  dd       d {  7   Y d }~y d }~ww xY w7 7 # tL        jN                  jP                  $ rE}t;        j<                  d       | jG                  |jR                  d       d {  7   Y d }~y d }~wt8        $ r4 t;        j<                  d       | jG                  dd       d {  7   Y y w xY ww)Nzsec-websocket-protocolr  r  r   subprotocol)r9  r  r  r  r%  )r_  c                  "   K   t               S wrP  rI   r  s   rg   return_bodyz0realtime_websocket_endpoint.<locals>.return_bodyJ  s     %e,,s   r  
_arealtime)r   r  r  r!  r  r  rY  r`  ra  r  r_  r9  r  zRealtime pre-call errorr  guardrail_error)rV   r`   )rV   r  i  zPre-call error)r'  reasonr  r  zInvalid status codezInternal server errorr^  )*r%  r  r  r  acceptr   r  r  r  r  r_  rY   rl  r*  r  _urlr  r    common_processing_pre_call_logicr  r!  r  r  rY  r`  ra  r  r_  rp  r}   r  	send_textr  rF  r  rj  r   r  
websockets
exceptionsInvalidStatusCoder#  )r  r9  r  r  r  prequested_protocolsaccept_kwargsr  r  gheaders_listr_  r   r
  r  r  r  r  s    `                 rg   realtime_websocket_endpointr    s      ##''(@AGRNNsS779 	
	 
 M':1'=m$
)


+]
+++ T"A%"PQL
 $D 1;1A1A#1FTA!'')aggiT\ 	++I6<"=L+002E#E)E"G==GL- GL #@T"J
$ .NN-//%!-!5+'# O 
 
	
HI$5 !&#!!	
 
 { , U6
  &&'@A	%%

 '$5'*1v"
 
 
  		oo40@oAAA#,
 	  22 P&&'<=oo1==9NoOOO I&&'>?oo40GoHHHIs  1L*'G##L*>G(?AL*G+G+)A<L*&AG2 +G0,G2 4J
 J	J
 JJ
 "L*+L*0G2 2	J;I>6II
II>	II>II>3I64I>9L*>JL*J
 J
 
L''5K'KK'"L*'7L'L!L'$L*&L''L*z/v1/assistants
assistantsz/assistantsc                 b  K   i }	 | j                          d{    t        || t        |t        t               d{   }t
        't        ddt        j                  j                  i      t        j                  di | d{   }t        j                  t        j                  |j                  dd      d	             t!        |d
i       xs i }|j                  dd      xs d}|j                  dd      xs d}|j                  dd      xs d}|j"                  j%                  t'        j(                  ||||t        t!        |dd      ||             |S 7 H7 &7 # t*        $ r9}	t        j-                  ||	|       d{  7   t/        j0                  dj3                  t5        |	                   t/        j6                  t9        j:                                t=        |	t              r\t?        t!        |	dt5        |	j@                              t!        |	dd      t!        |	dd      t!        |	dtB        jD                              t5        |	       }
t?        t!        |	d|
      t!        |	dd      t!        |	dd      t!        |	dd      t!        |	dd            d}	~	ww xY ww)z
    Returns a list of assistants.

    API Reference docs - https://platform.openai.com/docs/api-reference/assistants/listAssistants
    Nr  rx  r  r  r  r  r  r  r  r  r  r:  r  r  rs  zClitellm.proxy.proxy_server.get_assistants(): Exception occured - {}r`   rV   rw  r  r#  ry  r'  r  r^  )#r  r   r  r!  r  r  r'  r*   no_llm_routerr  aget_assistantsr  r  r  r  r  r  r%  rJ  r   r  rp  r|  r}   r  ru   r  re  r  r  r  r?   r  r0  r  r   r|  r  r  ri  r  r  r  r:  r  r  s              rg   get_assistantsr     s    * DIlln 1-/%
 
 2C2Q2Q2W2W(X  $33;d;; 	33 $):B ?	 4 	
  *:B?E2 $$Z6<"!%%k48>B	 $$Z6<"  '')<<"3!#!$%68NPRS!+		
 [ 	
 <:  66/ATX 7 
 	
 	
 	""QXXA	

 	""9#7#7#9:a' 9c!((m<Q/a&1Qv/J/JK	  q6(I 9i8Q/a&1#Avt4Qs3 'si   J/E) E!$E) E$A	E) E'	CE)  J/!E) $E) 'E) )
J,3J'FDJ''J,,J/c                   K   i }	 | j                          d{   }t        j                  |      }t        || t        |t
        t               d{   }t        't        ddt        j                  j                  i      t        j                  di | d{   }t        j                  t        j!                  |j#                  dd      d	             t%        |d
i       xs i }|j#                  dd      xs d}|j#                  dd      xs d}|j#                  dd      xs d}	|j&                  j)                  t+        j,                  ||||	t
        t%        |dd      ||             |S 7 ]7 &7 # t.        $ r8}
t        j1                  ||
|       d{  7   t3        j4                  dj7                  t9        |
                   t3        j:                  t=        j>                                tA        |
t              r\tC        t%        |
dt9        |
jD                              t%        |
dd      t%        |
dd      t%        |
dtF        jH                              t9        |
       }tC        t%        |
d|      t%        |
dd      t%        |
dd      t%        |
dt%        |
dd                  d}
~
ww xY ww)z~
    Create assistant

    API Reference docs - https://platform.openai.com/docs/api-reference/assistants/createAssistant
    Nr  rx  r  r  r  r  r  r  r  r  r  r:  r  r  rs  zElitellm.proxy.proxy_server.create_assistant(): Exception occured - {}r`   rV   rw  r  r#  ry  r'  r^  )%r  r  r  r   r  r!  r  r  r'  r*   r  r  acreate_assistantsr  r  r  r  r  r  r%  rJ  r   r  rp  r|  r}   r  ru   r  re  r  r  r  r?   r  r0  r  )r   r|  r  r  r  ri  r  r  r  r:  r  r  s               rg   create_assistantr#    s    * DI\\^#||D! 1-/%
 
 2C2Q2Q2W2W(X  $66>>> 	33 $):B ?	 4 	
  *:B?E2 $$Z6<"!%%k48>B	 $$Z6<"  '')<<"3!#!$%68NPRS!+		
 ] $
 ?:  66/ATX 7 
 	
 	
 	""SZZA	

 	""9#7#7#9:a' 9c!((m<Q/a&1Qv/J/JK	  q6(I 9i8Q/a&1Q=#(FG	 'sk   KE> E69E> E9A	E> E<CE> 5K6E> 9E> <E> >
K J;#F&$DJ;;K  Kz"/v1/assistants/{assistant_id:path}z/assistants/{assistant_id:path}assistant_idc                 .  K   i }	 t        || t        |t        t               d{   }t        't        ddt        j                  j                  i      t	        j                  dd|i| d{   }t        j                  t        j                  |j                  dd      d	
             t        |di       xs i }|j                  dd      xs d}|j                  dd      xs d}|j                  dd      xs d}	|j                   j#                  t%        j&                  ||||	t        t        |dd      ||             |S 7 %7 # t(        $ r8}
t        j+                  ||
|       d{  7   t-        j.                  dj1                  t3        |
                   t-        j4                  t7        j8                                t;        |
t
              r\t=        t        |
dt3        |
j>                              t        |
dd      t        |
dd      t        |
dt@        jB                              t3        |
       }t=        t        |
d|      t        |
dd      t        |
dd      t        |
dt        |
dd                  d}
~
ww xY ww)z~
    Delete assistant

    API Reference docs - https://platform.openai.com/docs/api-reference/assistants/createAssistant
    r  Nrx  r  r  r$  r  r  r  r  r  r  r  r:  r  r  rs  zElitellm.proxy.proxy_server.delete_assistant(): Exception occured - {}r`   rV   rw  r  r#  ry  r'  r^  )"r   r  r!  r  r  r'  r*   r  r  adelete_assistantr  r  r  r  r  r  r%  rJ  r   r  rp  r|  r}   r  ru   r  re  r  r  r  r?   r  r0  r  )r   r$  r|  r  r  ri  r  r  r  r:  r  r  s               rg   delete_assistantr'  Y   s    , DG 1-/%
 
 2C2Q2Q2W2W(X  $55X<XSWXX 	33 $):B ?	 4 	
  *:B?E2 $$Z6<"!%%k48>B	 $$Z6<"  '')<<"3!#!$%68NPRS!+		
 U
 Y:  66/ATX 7 
 	
 	
 	""SZZA	

 	""9#7#7#9:a' 9c!((m<Q/a&1Qv/J/JK	  q6(I 9i8Q/a&1Q=#(FG	 'Y   J E EAE 2E3CE 
JE E 
JJ5E86DJJJz/v1/threadsz/threadsc                 `  K   i }	 | j                          d{    t        || t        |t        t               d{   }t
        't        ddt        j                  j                  i      t        j                  di | d{   }t        j                  t        j                  |j                  dd      d	             t!        |d
i       xs i }|j                  dd      xs d}|j                  dd      xs d}|j                  dd      xs d}|j"                  j%                  t'        j(                  ||||t        t!        |dd      ||             |S 7 H7 &7 # t*        $ r8}	t        j-                  ||	|       d{  7   t/        j0                  dj3                  t5        |	                   t/        j6                  t9        j:                                t=        |	t              r\t?        t!        |	dt5        |	j@                              t!        |	dd      t!        |	dd      t!        |	dtB        jD                              t5        |	       }
t?        t!        |	d|
      t!        |	dd      t!        |	dd      t!        |	dt!        |	dd                  d}	~	ww xY ww)zs
    Create a thread.

    API Reference - https://platform.openai.com/docs/api-reference/threads/createThread
    Nr  rx  r  r  r  r  r  r  r  r  r  r:  r  r  rs  zClitellm.proxy.proxy_server.create_threads(): Exception occured - {}r`   rV   rw  r  r#  ry  r'  r^  )#r  r   r  r!  r  r  r'  r*   r  r  acreate_threadr  r  r  r  r  r  r%  rJ  r   r  rp  r|  r}   r  ru   r  re  r  r  r  r?   r  r0  r  r  s              rg   create_threadsr+     s    * DHlln 1-/%
 
 2C2Q2Q2W2W(X  $22:T:: 	33 $):B ?	 4 	
  *:B?E2 $$Z6<"!%%k48>B	 $$Z6<"  '')<<"3!#!$%68NPRS!+		
 [ 	
 ;:  66/ATX 7 
 	
 	
 	""QXXA	

 	""9#7#7#9:a' 9c!((m<Q/a&1Qv/J/JK	  q6(I 9i8Q/a&1Q=#(FG	 'si   J.E) E!$E) E$A	E) E'	CE)  J.!E) $E) 'E) )
J+3J&FDJ&&J++J.z/v1/threads/{thread_id}z/threads/{thread_id}	thread_idc                 .  K   i }	 t        || t        |t        t               d{   }t        't        ddt        j                  j                  i      t	        j                  dd|i| d{   }t        j                  t        j                  |j                  dd      d	
             t        |di       xs i }|j                  dd      xs d}|j                  dd      xs d}|j                  dd      xs d}	|j                   j#                  t%        j&                  ||||	t        t        |dd      ||             |S 7 %7 # t(        $ r8}
t        j+                  ||
|       d{  7   t-        j.                  dj1                  t3        |
                   t-        j4                  t7        j8                                t;        |
t
              r\t=        t        |
dt3        |
j>                              t        |
dd      t        |
dd      t        |
dt@        jB                              t3        |
       }t=        t        |
d|      t        |
dd      t        |
dd      t        |
dt        |
dd                  d}
~
ww xY ww)zs
    Retrieves a thread.

    API Reference - https://platform.openai.com/docs/api-reference/threads/getThread
    r  Nrx  r  r  r,  r  r  r  r  r  r  r  r:  r  r  rs  z?litellm.proxy.proxy_server.get_thread(): Exception occured - {}r`   rV   rw  r  r#  ry  r'  r^  )"r   r  r!  r  r  r'  r*   r  r  aget_threadr  r  r  r  r  r  r%  rJ  r   r  rp  r|  r}   r  ru   r  re  r  r  r  r?   r  r0  r  r   r,  r|  r  r  ri  r  r  r  r:  r  r  s               rg   
get_threadr0  !  s    , DE0-/%
 
 2C2Q2Q2W2W(X  $//L)LtLL 	33 $):B ?	 4 	
  *:B?E2 $$Z6<"!%%k48>B	 $$Z6<"  '')<<"3!#!$%68NPRS!+		
 U
 M:  66/ATX 7 
 	
 	
 	""MTTA	

 	""9#7#7#9:a' 9c!((m<Q/a&1Qv/J/JK	  q6(I 9i8Q/a&1Q=#(FG	 'r(  z /v1/threads/{thread_id}/messagesz/threads/{thread_id}/messagesc                   K   i }	 | j                          d{   }t        j                  |      }t        || t        |t
        t               d{   }t        't        ddt        j                  j                  i      t        j                  dd|i| d{   }t        j                  t        j!                  |j#                  dd      d	
             t%        |di       xs i }|j#                  dd      xs d}|j#                  dd      xs d}	|j#                  dd      xs d}
|j&                  j)                  t+        j,                  |||	|
t
        t%        |dd      ||             |S 7 _7 (7 # t.        $ r8}t        j1                  |||       d{  7   t3        j4                  dj7                  t9        |                   t3        j:                  t=        j>                                tA        |t              r\tC        t%        |dt9        |jD                              t%        |dd      t%        |dd      t%        |dtF        jH                              t9        |       }tC        t%        |d|      t%        |dd      t%        |dd      t%        |dt%        |dd                  d}~ww xY ww)zv
    Create a message.

    API Reference - https://platform.openai.com/docs/api-reference/messages/createMessage
    Nr  rx  r  r  r,  r  r  r  r  r  r  r  r:  r  r  rs  zAlitellm.proxy.proxy_server.add_messages(): Exception occured - {}r`   rV   rw  r  r#  ry  r'  r^  )%r  r  r  r   r  r!  r  r  r'  r*   r  r  a_add_messager  r  r  r  r  r  r%  rJ  r   r  rp  r|  r}   r  ru   r  re  r  r  r  r?   r  r0  r  r   r,  r|  r  r  r  ri  r  r  r  r:  r  r  s                rg   add_messagesr4  z!  s    , DI\\^#||D! 1-/%
 
 2C2Q2Q2W2W(X  $11NINNN 	33 $):B ?	 4 	
  *:B?E2 $$Z6<"!%%k48>B	 $$Z6<"  '')<<"3!#!$%68NPRS!+		
 ] $
 O:  66/ATX 7 
 	
 	
 	""OVVA	

 	""9#7#7#9:a' 9c!((m<Q/a&1Qv/J/JK	  q6(I 9i8Q/a&1Q=#(FG	 'sk   KF  E89F  E;AF  E> CF  7K8F  ;F  >F   
K
J=%F(&DJ==KKc                 .  K   i }	 t        || t        |t        t               d{   }t        't        ddt        j                  j                  i      t	        j                  dd|i| d{   }t        j                  t        j                  |j                  dd      d	
             t        |di       xs i }|j                  dd      xs d}|j                  dd      xs d}|j                  dd      xs d}	|j                   j#                  t%        j&                  ||||	t        t        |dd      ||             |S 7 %7 # t(        $ r8}
t        j+                  ||
|       d{  7   t-        j.                  dj1                  t3        |
                   t-        j4                  t7        j8                                t;        |
t
              r\t=        t        |
dt3        |
j>                              t        |
dd      t        |
dd      t        |
dt@        jB                              t3        |
       }t=        t        |
d|      t        |
dd      t        |
dd      t        |
dt        |
dd                  d}
~
ww xY ww)z
    Returns a list of messages for a given thread.

    API Reference - https://platform.openai.com/docs/api-reference/messages/listMessages
    r  Nrx  r  r  r,  r  r  r  r  r  r  r  r:  r  r  rs  zAlitellm.proxy.proxy_server.get_messages(): Exception occured - {}r`   rV   rw  r  r#  ry  r'  r^  )"r   r  r!  r  r  r'  r*   r  r  aget_messagesr  r  r  r  r  r  r%  rJ  r   r  rp  r|  r}   r  ru   r  re  r  r  r  r?   r  r0  r  r/  s               rg   get_messagesr7  !  s    , DE0-/%
 
 2C2Q2Q2W2W(X  $11NINNN 	33 $):B ?	 4 	
  *:B?E2 $$Z6<"!%%k48>B	 $$Z6<"  '')<<"3!#!$%68NPRS!+		
 U
 O:  66/ATX 7 
 	
 	
 	""OVVA	

 	""9#7#7#9:a' 9c!((m<Q/a&1Qv/J/JK	  q6(I 9i8Q/a&1Q=#(FG	 'r(  z/v1/threads/{thread_id}/runsz/threads/{thread_id}/runsc                   K   i }	 | j                          d{   }t        j                  |      }t        || t        |t
        t               d{   }t        't        ddt        j                  j                  i      t        j                  dd|i| d{   }d|v r)|d   du r"t        t        |||	      d
i        d{   S t        j                   t"        j%                  |j'                  dd      d             t)        |di       xs i }|j'                  dd      xs d}|j'                  dd      xs d}	|j'                  dd      xs d}
|j*                  j-                  t/        j0                  |||	|
t
        t)        |dd      ||             |S 7 7 U7 7 # t2        $ r8}t"        j5                  |||       d{  7   t7        j8                  dj;                  t=        |                   t7        j>                  tA        jB                                tE        |t              r\tG        t)        |dt=        |jH                              t)        |dd      t)        |dd      t)        |dtJ        jL                              t=        |       }tG        t)        |d|      t)        |dd      t)        |dd      t)        |dt)        |dd                  d}~ww xY ww) zi
    Create a run.

    API Reference: https://platform.openai.com/docs/api-reference/runs/createRun
    Nr  rx  r  r  r,  r  Tr  r  )	generatorr  r%  r  r  r  r  r  r  r  r:  r  r  rs  z?litellm.proxy.proxy_server.run_thread(): Exception occured - {}r`   rV   rw  r  r#  ry  r'  r^  )'r  r  r  r   r  r!  r  r  r'  r*   r  r  arun_threadr   r  r  r  r  r  r  r  r%  rJ  r   r  rp  r|  r}   r  ru   r  re  r  r  r  r?   r  r0  r  r3  s                rg   
run_threadr;  <"  s    , DT\\^#||D!0-/%
 
 2C2Q2Q2W2W(X  $//L)LtLL h4!7(9&7%!%
 /   	33 $):B ?	 4 	
  *:B?E2 $$Z6<"!%%k48>B	 $$Z6<"  '')<<"3!#!$%68NPRS!+		
 u $
 M
J  66/ATX 7 
 	
 	
 	""MTTA	

 	""9#7#7#9:a' 9c!((m<Q/a&1Qv/J/JK	  q6(I 9i8Q/a&1Q=#(FG	 's   K5F0 F%9F0 F(AF0 F+ ,F0 F.F0 K5CF0 $K5%F0 (F0 +F0 .F0 0
K2:K-GDK--K22K5)BaseTokenCounterr  model_to_usec           	      d   | yddl m} | j                  di       j                  dd      }d}d}	  ||| j                  di       j                  d      | j                  di       j                  d      | j                  di       j                  d	      
      \  }}}}ddlm} ddlm}	  ||      }
|
r(|	j                  ||
      }||j                         ||fS y# t        $ rH |j                  d      sd|j                         v r"ddlm}  |       }|j                         ||fcY S Y yw xY w)z
    Auto-route to the correct provider's token counter based on model/deployment.
    Uses the existing get_provider_model_info infrastructure with switch-case pattern.
    Nr   )rz  r  r9  r  r  r:  r  )r9  r  r:  r  )LlmProviders)ProviderConfigManager)r9  r  z
anthropic/	anthropic)AnthropicModelInfo)NNN)1litellm.litellm_core_utils.get_llm_provider_logicrz  r  rO  r?  rm  r@  get_provider_model_infoget_token_counterrp  r@  r  #litellm.llms.anthropic.common_utilsrB  )r  r=  rz  
full_modelr9  r  dynamic_api_keyr:  r?  r@  llm_provider_enumprovider_model_inforB  anthropic_model_infos                 rg   _get_provider_token_counterrL  "  sj    R 0"599'2FJE)-$X@P */? D H H%!  ^^$4b9==jINN#3R8<<YGA
="OX 	57 ))<= "7"O"O +< #P # #.'99;'    X  .+AQAQAS2SN#5#7 '99;UDWWW	 3T Xs   B+C AD/.D/z/utils/token_counterz	llm utils)r  rY  response_modelcall_endpointc           	      p  K   ddl m} | j                  }| j                  }| j                  }| j
                  }| j                  }|||t        dd      d}d}	d}
t        *	 t        j                  | j                  i        d{   }|g|j                  d	i       j                  d
      }	|j                  di       }
t        |j                  d	i              d|	v r|	j!                  dd      d   }	|	xs | j                  }d}d}|du r|t#        ||      \  }}}||}||j%                  |      du r|j'                  |xs d|||| j                  ||       d{   }|||j(                  du rnt         j*                  du r+t-        |j.                  xs ddd
|j0                  xs d      t        j2                  d|j0                   d|j.                   d       n||S t         j*                  du rt-        ddd
d      d}|
't5        t6        t8           |
j                  dd            }t         j:                  j=                  ||      }t?        |d         } |||||      }tA        || j                  ||       S 7 # t        $ r t        j                  d       Y !w xY w7 Ow)!z
    Args:
        request: TokenCountRequest
        call_endpoint: bool - When set to "True" it will call the token counting endpoint - e.g Anthropic or Google AI Studio Token Counting APIs.

    Returns:
        TokenCountResponse
    r   )token_counterNrd  z/prompt or messages or contents must be providedr  )r9  request_kwargszVlitellm.proxy.proxy_server.token_counter(): Exception occured while getting deploymentr  r9  r^  r  r  Tr  r  )r=  rk   contentsr  r  r  systemzToken counting failedtoken_counting_errorrx  ry  z Provider token counting failed (z): z". Falling back to local tokenizer.z?Token counting is disabled and no provider API result availabletoken_counting_disabledi  custom_tokenizer)r9  rW  rV   )r9  r  rk   rW  )r  r  
model_usedtokenizer_type)!rg  rP  r  rk   rS  r  rT  r'  r  async_get_available_deploymentr9  rp  r}   r  r  rP   r  rL  should_use_token_counting_apicount_tokensr  disable_token_counterr?   r  r#  r|  r   r   r  r  _select_tokenizerr  rN   )r   rN  rP  r  rk   rS  r  rT  r  rz  r^  r=  provider_counterr  _modelr  rW  _tokenizer_usedtokenizer_usedr  s                       rg   rP  rP  "  sJ     & ^^FHHMME^^F
 ~(*x/?$U
 	
 ,0J)-J		)HHmm!  I   J '^^,<bAEEgN^^L"5
":>>2BB#GH$$!3!9!9#q!A!!D 	+gmm 
 48)-!78S9
5&"5 !L#::$7 ;  
 ,88)/R!!%%mm 9  F !flld&:00D8( & 4 4 O8O3%#//63	  %,,6v7I7I6J#fNbNbMc d7 7 # $$,U*	
 	
 >B/0NN-t4
 mm55-= 6 O 01N (	L !mm%	 A  	 **h 		FsJ   A"J6%$J 	J
J CJ6$J3%D&J6J J0,J6/J00J6z/utils/supported_openai_params)r  rY  c                    K   	 t        j                  |       \  } }}}dt        j                  | |      iS # t        $ r t	        dddj                  |       i      w xY ww)a*  
    Returns supported openai params for a given litellm model name

    e.g. `gpt-4` vs `gpt-3.5-turbo`

    Example curl:
    ```
    curl -X GET --location 'http://localhost:4000/utils/supported_openai_params?model=gpt-3.5-turbo-16k'         --header 'Authorization: Bearer sk-1234'
    ```
    r  supported_openai_paramsr9  r  rd  r  zCould not map model={}r  )rg  rz  get_supported_openai_paramsrp  r'  ru   )r9  r  r  s      rg   rd  rd  }#  sx     "

+2+C+C%+P("Aq%w'J'J1D(
 	

  
W.F.M.Me.T$U
 	

s   A#38 A#(A  A#z/utils/transform_requestc                 R   K   ddl m}  || j                  | j                        S w)Nr   )return_raw_request)endpointry  )rm  rh  r  request_body)r   rh  s     rg   transform_requestrk  #  s$      1w'8'8AUAUVVs   %'rv  c                 |  K   |'t        ddt        j                  j                  i      g }| D ]  }|j	                  di       j	                  dd      }|(|j
                  j                  j                  d|i       d{   }|[|j                  |j                  k(  su|j                  |        |S 7 6w)	
    Check if model is in db

    Check if db model is 'created_by' == user_api_key_dict.user_id

    Only return models that match
    Nrx  r  r  r^  r{  r  r  )r'  r*   db_not_connected_errorr  r  r  rr  r  r  r  r  )rv  r  r]  filtered_modelsr9  r{  r  s          rg   _check_if_model_is_user_addedrp  #  s      .EEKKL
 	
 O 	.YY|R(,,T48:&))AAMMr" N 
 
 ""&7&?&??&&u-	. 
s   BB<B:B<B<%B<user_rowc                     g }| D ]U  }|j                  di       j                  dd      }|(||j                  v s7|j                  t        t        |             W |S )zm
    Check if model is a team model

    Check if user is a member of the team that the model belongs to
    r^  r  N)r  r  r  r   r	   )rv  rq  user_team_modelsr9  model_team_ids        rg   _check_if_model_is_team_modelru  #  se     $& ;		,377	4H$. ''T5(9:; ri   rs  c                   K   |'t        ddt        j                  j                  i      t	        | ||       d{   } |j
                  r]	 |j                  j                  j                  d|j
                  i       d{   }| t        |j                         xs g |
      z  } t        |       }|S 7 {7 6# t        $ r t        ddd	i      w xY ww)rm  Nrx  r  r  )rv  r  r]  r  r  rd  zUser not found)rv  rq  )rv  )r'  r*   rn  r  rp  r  r  litellm_usertabler  rp  ru  rf  r   )rs  r  r  r]  rq  unique_modelss         rg   non_admin_all_modelsry  #  s      .EEKKL
 	
 5+# J   	U*--??KK "3";";< L  H 	3,,.4"
 	

 7jIM-  	UCBR8STT	Us9   ;CB9C5B= B;B= 	1C;B= =CCteam_db_objects_typedc                    i }| D ]  }t        |j                        dk(  s&t        j                  j                  |j                  v r|j                         }|U|D ]  }|j                  di       j                  dd      }|(|j                  di       j                  dd      }d}|d}n||j                  v rd}|sd|j                  |t                     j                  |j                          |j                  D ]  }	|j                  |	|j                        }
|
#|
D ]Z  }|j                  di       j                  dd      }|(|j                  |t                     j                  |j                         \   |S )	z'
    Add team models to all models
    r   Nr^  r{  r  FTr8  r  )rn  rv  rA   all_proxy_modelsr  rf  r  r  ra  r&  add)rz  r  rg  team_objectr4  r9  r  team_model_idcan_add_modelr8  _modelss              rg   _add_team_models_to_all_modelsr  $  s    (*K,  ""#q( 1177;;M;MM#224J%' YE$yyr:>>tTJH' $)IIlB$?$C$CIt$TM$)M$,(,&+*=*==(,$#..x?CCKDWDWXY *00 

$33);3F3F 4  &!( #(99\2#>#B#B4#N#/'228SUCGG + 3 3
- B ri   
user_teamsc           	        K   g }| dk(  rS|j                   j                  j                          d{   }|D cg c]  }t        di |j	                          }}nX|j                   j                  j                  dd| ii       d{   }|D cg c]  }t        di |j	                          }}t        ||      }i }|j                         D ]  \  }}	t        |	      ||<    |S 7 c c}w 7 hc c}w w)z
    Get all models across all teams user is in.

    1. Get all teams user is in
    2. Get all models across all teams
    3. Return {"model_id": ["team_id1", "team_id2"]}
    r   Nr  r  r  )rz  r  r^  )r  litellm_teamtablers  r:   r  r  r  r  )
r  r]  r  rz  team_db_objectsteam_db_objectrg  returned_team_modelsr  team_idss
             rg   get_all_team_modelsr  4$  s.     68S - 0 0 B B L L NN #2!
 < 9 9 ;<!
 !

 !. 0 0 B B L LtZ01 !M !
 
 #2!
 < 9 9 ;<!
 !

 13K 24)//1 8()-hX&8  3 O!


!
s>   /C:C,C: C.0C:
C3C: C53:C:.C:5C:user_db_objectc                     g }| j                   D ]T  }|j                  |      }||D ]8  }|j                  di       j                  dd      }|(|j                  |       : V |S )z7
    Get all models that user has direct access to
    r8  Nr^  r{  )rv  rf  r  r  )r  r  direct_access_modelsr9  deploymentsr  r  s          rg   get_direct_access_modelsr  `$  s     ')&& : //5/A") :
%>>,;??dK'(//9::  ri   c                   K   d}g }| j                   t        j                  k(  rd}|j                  d      }n~| j                  r|j
                  j                  j                  d| j                  i       d{   }|6t        di |j                         }|j                  xs g }t        ||      }|t        |||       d{   }|D ]  }	|	j                  d	i       j                  d
d      }
|	j                  d	i       j                  dd      }|
Jd}||j                  |
g       }|r	||v rd}nd}|sn|j                  |
g       |	d	   d<    |D ]4  }	|	j                  d	i       j                  d
d      }
|
(|
|v s-d|	d	   d<   6 |D 	cg c]H  }	|	j                  d	i       j                  dd      s"|	j                  d	i       j                  dg       r|	J }}	|S 7 m7  c c}	w w)z5
    Get all models across all teams user is in.
    Nr   T)exclude_team_modelsr  r  )r  r  )r  r]  r  r^  r{  r  Faccess_via_team_idsdirect_accessr^  )	user_roler<   PROXY_ADMINr  r  r  rw  r  r;   r  r  r  r  r  )r  r]  r  rs  r  r  r  user_objectrg  r`  r  team_only_model_idcan_use_modelr  s                 rg   %get_all_team_and_direct_access_modelsr  s$  sH     <@J&(""&6&B&BB
)77 $  8  
 
	"	"	.,//AAMM/778  N  
 
 %+Jn.G.G.IJK$**0bJ#;*%$ 
 /!'!
 

 ! 	Fzz,377dCH!'L"!=!A!A)T!R# %%1*x<H$6($B(,$(M BM// "CF<()>?	$  9::lB/33D$?H0D$D48F< 19 !::lB'++OUC::lB'++,A2F 	J  _

:sR   A8G2:G';AG2
G*AG2#G2?AG2G2G2AG-#G2*G2-G2re  c                    | j                  di       }|du r/d}||j                  | i d      xs d}nd}t        |      }|| d<   t        | 	      }|i k(  r;| j                  d
i       }|j                  dd      }	 t	        j
                  |	      }|i k(  re| j                  d
i       }|j                  dd      }|r?|j                  d      }	t        |	      dkD  r|	d   }	 t	        j
                  ||	d         }|j                         D ]  \  }
}|
|vs|||
<    || d<   t        | dh      } | S # t        $ r i }Y w xY w# t        $ r i }Y Uw xY w)a  
    Enrich a model dictionary with litellm model info (pricing, context window, etc.)
    and remove sensitive information.

    Args:
        model: Model dictionary to enrich
        debug: Whether to include debug information like openai_client
        llm_router: Optional router instance for debug info

    Returns:
        Enriched model dictionary with sensitive info removed
    r^  Trw  Nasync)r  ry  client_typellm_router_is_Noneopenai_clientr  r  r9  r  r   r  re  litellm_credential_name)excluded_keys)r  _get_clientr  r  rg  r  rp  r  rn  r  r   )r9  re  r  r^  _openai_clientr  r  r  r  split_modelr  r  s               rg   $_enrich_model_info_with_litellm_datar  $  s     <,J}!&&%PW&X  
 2NN+!.o 0e< R#3R8&**7D9	$!(!7!7m!L R#3R8&**7D9'--c2K;!# +B(%,%;%;'[^&"
 #((* 1JJqM %E, 278E L5  	$!#	$  (%'"(s$   <D3 "E 3E EEEsearchpagesizer  sort_byc                   K   |r|j                         s| dfS |j                         j                         }| D cg c]'  }||j                  dd      j                         v s&|) }	}g }
t               }|	D ]^  }|j                  di       }|j                  dd      }|j                  d      }|r|r|j	                  |       N|
j                  |       ` t        |
      }t        |      }||z   }g }d}||z  }|)	 d|d	d
i}|rddt        |      ii|d<   |j                  j                  j                  |       d{   }||z   }|rb|dkD  r|j                  j                  j                  ||       d{   }|D ](  }|j                  |g      }|s|j                  |       * nu||k  rpt        ||z
  |      }|dkD  r\|j                  j                  j                  ||       d{   }|D ](  }|j                  |g      }|s|j                  |       * n|}|	|z   }||fS c c}w 7 7 7 F# t        $ r-}t!        j"                  dt%        |              |}Y d}~Ed}~ww xY ww)aC  
    Apply search filter to models, querying database for additional matching models.

    Args:
        all_models: List of models to filter
        search: Search term (case-insensitive)
        page: Current page number
        size: Page size
        prisma_client: Prisma client for database queries
        proxy_config: Proxy config for decrypting models
        sort_by: Optional sort field - if provided, fetch all matching models instead of paginating at DB level

    Returns:
        Tuple of (filtered_models, total_count). total_count is None if not searching.
    Nr8  r  r^  r  Fr{  r   insensitive)containsmodenotr  r  r  )r  takez,Error querying database models with search: )r  r  r  r&  r~  r  rn  r  r  rr  countrs  r  r  ro  rp  r}   r  r  )rs  r  r  r  r]  r  r  search_lowerrt  filtered_router_modelsfiltered_config_modelsdb_model_ids_in_routerr^  is_db_modelr  config_models_countdb_models_in_router_countrouter_models_countr  db_models_total_countmodels_needed_for_pagedb_where_conditionsearch_total_countdb_models_rawr  decrypted_modelsmodels_to_fetchr  ro  s                                rg   _apply_search_filter_to_modelsr  $  s    0 4<<>'')L |R1H1N1N1P!P 
   U# -UU<,
 nnZ7>>$'8"&&x0"))!,- 45 #$: ;-0II I!D[  G	5  ,)2 &D$'=">?2":. $&&>>DD, E   " "57L!L (1,+..FFPP"4!6 Q   " %2 ?+7+R+R%J,( ,%,,-=>? ')??&).1DD-'O
 '*"/"2"2"J"J"T"T&8%4 #U #  & )6 CH/;/V/V!)
0,  0 ) 0 01A BC 1 -y8O...WZ.  	5 **>s1vhG "5	5s   9I7'H3#H3'BI7 AH> H8:H> ?H: H> AH> 5H<6H> H> 'I78H> :H> <H> >	I4#I/*I7/I44I7dtc                    | yt        | t              r	 | j                  d      r| j                  dd      n| }t	        j
                  |      }|j                  "|j                  t        j                        }|S |j                  t        j                        }|S t        | t              rK| j                   | j                  t        j                        S | j                  t        j                        S y# t        t        f$ r Y yw xY w)a  
    Normalize a datetime value to a timezone-aware UTC datetime for sorting.

    This function handles:
    - None values: returns None
    - String values: parses ISO format strings and converts to UTC-aware datetime
    - Datetime objects: converts naive datetimes to UTC-aware, and aware datetimes to UTC

    Args:
        dt: Datetime value (None, str, or datetime object)

    Returns:
        UTC-aware datetime object, or None if input is None or cannot be parsed
    NZz+00:00tzinfo)r  r  rd  r	  r   r  r  r   utc
astimezoner  r  )r  dt_str	parsed_dts      rg   _normalize_datetime_for_sortingr  %  s     
z"c	24++c2BRZZX.F ..v6I'%--X\\-B	  &00>	 "h99::X\\:22}}X\\** N+ 		s   A'C: = C: :DDasc
sort_orderc           	         rdvr| S |j                         dk(  dt        t        t        f   dt        ffd}	 t	        | |      }|S # t
        $ r0}t        j                  d dt        |              | cY d	}~S d	}~ww xY w)
a  
    Sort models by the specified field and order.

    Args:
        all_models: List of models to sort
        sort_by: Field to sort by (model_name, created_at, updated_at, costs, status)
        sort_order: Sort order (asc or desc)

    Returns:
        Sorted list of models
    )r8  r  r  costsr0  descr9  r.  c                 \   | j                  di       }
dk(  r | j                  dd      j                         S 
dk(  r~|j                  d      }t        |      }|^	s.t        j                  j                  t        j                        S t        j                  j                  t        j                        S |S 
dk(  r~|j                  d      }t        |      }|^	s.t        j                  j                  t        j                        S t        j                  j                  t        j                        S |S 
dk(  rP|j                  dd	      xs d	}|j                  d
d	      xs d	}||z   }|d	k(  r	st        d      S t        d      S |S 
dk(  r|j                  dd      }|S y )Nr^  r8  r  r  r  r  r  input_cost_per_tokenr   output_cost_per_tokenr  z-infr0  r  F)
r  r  r  r   maxr	  r   r  ro  r  )r9  r^  r  normalized_dtr  
input_costoutput_cost
total_costr  r6  r  s            rg   get_sort_keyz"_sort_models.<locals>.get_sort_key%  s   YY|R0
l"99\2.4466$#5J;JGM$ # LL(((= "--X\\-B
 ! $#5J;JGM$ # LL(((= "--X\\-B
 ! #(>BGaJ$..)@!DIK#k1JQ+2uU|EfE !~~j%8HOri   )r  r6  zError sorting models by r\   N)r  r	   r  r   r8  rp  r}   r  )rs  r  r  r  sorted_modelsr  r6  s    `    @rg   _sort_modelsr  %  s      g &   F*G+DcN +s +Zz|WM &&)A'"SQRVH'UVs   A 	B%B=BBtotal_countc                     |t        |       }|dz
  |z  }|dkD  r| |z   nd}| |||z    }t        j                  d| d| d| d| d| 
       |||||dS )	aD  
    Paginate models and return response dictionary.

    Args:
        all_models: List of all models
        page: Current page number
        size: Page size
        total_count: Total count (if None, uses len(all_models))
        search: Search term (for logging)

    Returns:
        Paginated response dictionary
    r  r   zPagination: skip=z, take=z, total_count=z, total_pages=z	, search=r  r  current_pagetotal_pagesr  )rn  r}   re  )rs  r  r  r  r  skipr  paginated_modelss           rg   _paginate_models_responser  &  s    ( *o1HD-81_[LD()!K!$5
D6n[MXcWddmntmuv
 !"" ri   c           	        K   	 |j                   j                  j                  d|i       d{   }|t        j                  d| d       g S t        di |j                         }t               }t        |j                        dk(  s&t        j                  j                  |j                  v r|r|j!                         ng }||D ]k  }	|	j#                  d	i       j#                  d
d      }
|
(|	j#                  d	i       j#                  dd      }d}|d}n||k(  rd}|s[|j%                  |
       m nh|j                  D ]Y  }|r|j!                  ||      ng }||D ]8  }	|	j#                  d	i       j#                  d
d      }
|
(|j%                  |
       : [ 	 |j                  rt        j                  j                  |j                  vrc|j                   j&                  j)                  dd|j                  ii       d{   }|D ]"  }|j*                  }
|
s|j%                  |
       $ g }| D ]  }|j#                  d	i       }|j#                  d
d      }
|j#                  dd      r|j/                  |       K|j#                  dg       }t1        |t2              r||v r|j/                  |       |
s|
|v s|j/                  |        |S 7 # t        $ r0}t        j                  d| dt        |              g cY d}~S d}~ww xY w7 # t        $ r/}t        j,                  d| dt        |              Y d}~d}~ww xY ww)a  
    Filter models by team ID. Returns models where:
    - direct_access is True, OR
    - team_id is in access_via_team_ids

    Also searches config and database for models accessible to the team.

    Args:
        all_models: List of models to filter
        team_id: Team ID to filter by
        prisma_client: Prisma client for database queries
        llm_router: Router instance for config queries

    Returns:
        Filtered list of models
    r  r  NzTeam z not found in databasezError fetching team r\   r   r^  r{  FTr|  r8  r  z(Error querying database models for team r  r  r^  )r  r  r  r}   r|  r:   r  rp  r  r  r&  rn  rv  rA   r}  r  rf  r  r~  rr  rs  r  re  r  r  r  )rs  r  r]  r  r  r  r  team_accessible_model_idsr4  r9  r  r  r  r8  r  r  r  ro  r`  r^  r  s                        rg   _filter_models_by_team_idr  *&  s    .,//AAMMg&  N  
 
 ! ((5	9O)PQI'F.*C*C*EF +.% 	K1$--33{7I7II 5?Z..0B
!# < 99\26::4F# %		, ; ? ?	4 P % ($(M"g-$(M -11(;<  &,, 
	@J  ))Z)Q 
 "$ @E$yyr:>>tTJH+155h?@
	@
!2288@R@RR ,..FFPP#dK,>,>%?@ Q  I & <#,,-11(;< O +ZZb1
>>$- >>/51""6* )nn-BBG)40W@S5S""6* $==""6*%+( }
  &&)=gYbQ'QR	d  
""6wir#a&J	
 	

s   M+K K K MK *B:M%<M")MM"A)L LL $L 7B	MMMK 	L'%LLMLML 	M&$M
MMMc           	      T  K   d}|)|j                  |       }|rt        j                  |      }|L	 |j                  j                  j                  d| i       d{   }|r|j                  |g      }|r|d   }|V|T|j                         rD|j                         j                         }	|j                  dd	      }
|	|
j                         vrd}||gng }t        |      }||fS 7 # t        $ r.}t        j                  d|  dt        |              Y d}~d}~ww xY ww)
z<Find a model by its ID and optionally filter by search term.Nr  r  r  r   z$Error querying database for modelId r\   r8  r  )r  rl  rm  r  rr  r  r  rp  r}   r  r  r  r  r  rn  )r  r  r  r]  r  found_modelr  r  r  r  r8  rs  r  s                rg   _find_model_by_idr  &  sM     K  //8/<--4K 	*--EEQQ!8, R  H #/#J#JH:#V #"21"5K &,,.!<<>//1L$r:J:#3#3#55" #."9+rJ(+J)))3  	 **6xj3q6(K 	sA   0D(+C. C,C. >A.D(,C. .	D%7$D D( D%%D(z/v2/model/infozv2 - returns models available to the user based on their API key permissions. Shows model info from config.yaml (except api key and api base). Filter to just user-added models with ?user_models_only=true)r  r  rY  r  z!Specify the model name (optional)z%Only return models added by this userz.Return all models across all teams user is in.r  zPage number)r  ge2   z	Page sizez3Search model names (case-insensitive partial match)z,Search for a specific model by its unique IDzaFilter models by team ID. Returns models with direct_access=True or teamId in access_via_team_idszLField to sort by. Options: model_name, created_at, updated_at, costs, statuszSort order. Options: asc, descuser_models_onlyinclude_team_modelsmodelIdteamIdsortBy	sortOrderc           	        K   t         t         j                  sg d|d|dS t        't        ddt        j
                  j                  i      t        j                          d{    |(t        ||t         t        t               d{   \  }}nvt        j                  t         j                        }t        
|t        gz  }||D cg c]  }|d   |k(  s| }}t        ||xs d	||t        t        |

       d{   \  }}|rt        |t         | t               d{   }|rt        | t        t         |       d{   }t!        |      D ]  \  }}t#        |||ndt               ||<     |	H|	j%                         r8t'        ||	j%                         t        t                d{   }t)        |      }|t)        |      }|
r7|r#|j+                         dvrt        dd| d      t-        ||
|xs d      }t/        j0                  d|       t3        ||        d{   }t)        |      }t5        |||||      S 7 7 c c}w 7 W7 67 7 7 5w)zQ
    BETA ENDPOINT. Might change unexpectedly. Use `/v1/model/info` for now.
    Nr   r  rx  r  r  )r  r  r  r]  r  r8  r  )rs  r  r  r  r]  r  r  )rs  r  r  r]  )r  r]  r  rs  F)r9  re  r  )rs  r  r]  r  )r  r  rd  zInvalid sortOrder: z. Must be 'asc' or 'desc'r  )rs  r  r  all_models: %s)rv  r  )rs  r  r  r  r  )r  r4  r]  r'  r*   rn  r  r  r  r  rl  rm  rY  r  ry  r  rU  r  r  r  rn  r  r  r}   re  r   r  )r  r9  r  r  re  r  r  r  r  r  r  r  rs  r  rt  r  r`  s                    rg   model_info_v2r  &  s    \ !6!6 
 	
 .EEKKL
 	
 
!
!
### /@!'%0
 *
&
& ]]:#8#89
!:,&J%/L1\?e3K!LJL 0N!<R'%0
 *
&
& /!!/'	
 

 @/'!!	
 

 z* 
	6< ,%%!

1
 flln4!LLN'!	
 

 !_  _ */A,YK7PQ  "! )E

 /< 3+ J Z$& G $*
  M*


$
>s   A#I&%I&%I&IAI&II#I&I#I&&I' I&IA*I&2I"3A;I&.I$/ I&I&I&I&I&"I&$I&z/model/streaming_metricsz1View time to first token for models in spend logs)r  r  r  rY  _selected_model_group	startTimeendTimec                   K   t         5t        t        j                  j                  ddt
        j                        |xs! t        j                         t        d      z
  }|xs t        j                         }|j                         |j                         k(  }|rd}nd}t               }t         j                  j                  ||||       d {   }i }||D ]  }	|	d   }
|	d	   }|	d
   }d}|r|	d   }|}||vri ||<   n|	d   }|}|	d
   }||vri ||<   t        |      }d|
v rt        |
      }d|v r|j                  d      d   }|j!                  |       |||   |<    	 g }t#        t%        |j'                         d             }|D ]@  }dt        |      i}||   j'                         D ]
  \  }}|||<    |j)                  |       B |t+        |      dS y 7 w)Ninternal_errorrw  ry     r"  a  
            SELECT
                api_base,
                model_group,
                model,
                "startTime",
                request_id,
                EXTRACT(epoch FROM ("completionStartTime" - "startTime")) AS time_to_first_token
            FROM
                "LiteLLM_SpendLogs"
            WHERE
                "model_group" = $1 AND "cache_hit" != 'True'
                AND "completionStartTime" IS NOT NULL
                AND "completionStartTime" != "endTime"
                AND DATE("startTime") = DATE($2::timestamp)
            GROUP BY
                api_base,
                model_group,
                model,
                request_id
            ORDER BY
                time_to_first_token DESC;
        a  
            SELECT
                api_base,
                model_group,
                model,
                DATE_TRUNC('day', "startTime")::DATE AS day,
                AVG(EXTRACT(epoch FROM ("completionStartTime" - "startTime"))) AS time_to_first_token
            FROM
                "LiteLLM_SpendLogs"
            WHERE
                "startTime" BETWEEN $2::timestamp AND $3::timestamp
                AND "model_group" = $1 AND "cache_hit" != 'True'
                AND "completionStartTime" IS NOT NULL
                AND "completionStartTime" != "endTime"
            GROUP BY
                api_base,
                model_group,
                model,
                day
            ORDER BY
                time_to_first_token DESC;
        r:  r9  time_to_first_tokenr  
request_idr&  https:///openai/r   c                     | d   S Nr   r^  r  s    rg   <lambda>z)model_streaming_metrics.<locals>.<lambda>'      dSTg ri   r  dater  all_api_bases)r]  r?   r*   rn  r  r0  r)  r   r-  r   r	  r&  r  	query_rawr  r  r~  r  r8  r  r  r  )r  r  r  r  is_same_day	sql_query_all_api_basesdb_response_daily_entriesrt  	_api_baser`  r  
unique_key_request_id_day_combined_model_nameri  r&  rD  	model_keylatencys                         rg   model_streaming_metricsr	  |'  sI     %<<BB!66	
 	
 ?X\\^iQ.??I'G.."glln4K	0	. UN%((22()W K N% 	SJ":.I(F",-B"CJ(6(
n424N;/!%(!
&01F&G#~-+-N4(#&v; Y&'*9~$11';'A'A*'Ma'P$34?RN:&';<1	S4	  " f^%9%9%;AUVW! 	#CSX&E&4S&9&?&?&A +"	7#*i +OOE"		# !.1
 	
_ 	s   CG&G#DG&z/model/metricsz>View number of requests & avg latency per model on config.yamlz	gpt-4-32kr  customerc                 P  K   t         t        dddt        j                        |xs% t	        j
                         t        t              z
  }|xs t	        j
                         }||dk(  rd}||dk(  rd}d}t               }t         j                  j                  ||||||       d {   }i }	||D ]n  }
|
d	   }|
d
   }|
d   }|
d   }||	vri |	|<   t        |      }|d|v rt        |      }|d|v r|j                  d      d   }|j                  |       ||	|   |<   p 	 g }t        t        |	j!                         d             }	|	D ]@  }dt        |      i}|	|   j!                         D ]
  \  }}|||<    |j#                  |       B |t%        |      dS y 7 w)N Prisma Client is not initializedr  rw  ry  r  	undefinednulla  
        SELECT
            api_base,
            model_group,
            model,
            DATE_TRUNC('day', "startTime")::DATE AS day,
            AVG(EXTRACT(epoch FROM ("endTime" - "startTime")) / NULLIF("completion_tokens", 0)) AS avg_latency_per_token
        FROM
            "LiteLLM_SpendLogs"
        WHERE
            "startTime" >= $2::timestamp AND "startTime" <= $3::timestamp
            AND "model_group" = $1 AND "cache_hit" != 'True'
            AND (
                CASE
                    WHEN $4 != 'null' THEN "api_key" = $4
                    ELSE TRUE
                END
            )
            AND (
                CASE
                    WHEN $5 != 'null' THEN "end_user" = $5
                    ELSE TRUE
                END
            )
        GROUP BY
            api_base,
            model_group,
            model,
            day
        HAVING
            SUM(completion_tokens) > 0
        ORDER BY
            avg_latency_per_token DESC;
    r:  r9  r&  avg_latency_per_tokenr  r  r   c                     | d   S r	  r^  r	  s    rg   r	  zmodel_metrics.<locals>.<lambda>f(  r	  ri   r  r	  r	  )r]  r?   r0  r)  r   r-  r   r   r&  r  r	  r  r  r~  r  r8  r  r  r  )r  r  r  r  r  r	  r
	  r	  r	  r	  rt  r	  r`  r	  _avg_latency_per_tokenr	  ri  r&  rD  r	  r	  s                        rg   model_metricsr	   (  s      6!66	
 	
 MX\\^i_.MMI'G'[08{2!ID UN%((22()Wgx K N% 	PJ":.I(Fe$D%/0G%H">)')t$#&v; $y)@'*9~$#/JBV4V';'A'A*'Ma'P$349ON4 !56	P 	  " f^%9%9%;AUVW! 	#CSX&E&4S&9&?&?&A +"	7#*i +OOE"		# !.1
 	
K s   B*F&,F$-C8F&z/model/metrics/slow_responsesz/View number of hanging requests per model_groupc           	      ,  K   t         t        dddt        j                        ||dk(  rd}||dk(  rd}|xs% t	        j
                         t        t              z
  }|xs t	        j
                         }t        j                  j                  xs t        }t        |      }d}t         j                  j                  |||||||       d {   }|9|D ]4  }	|	j                  d	      xs d
}
d|
v r|
j!                  d      d   }
|
|	d	<   6 |S 7 Aw)Nr	  r  rw  ry  r	  r	  r  a  
SELECT
    api_base,
    COUNT(*) AS total_count,
    SUM(CASE
        WHEN ("endTime" - "startTime") >= (INTERVAL '1 SECOND' * CAST($1 AS INTEGER)) THEN 1
        ELSE 0
    END) AS slow_count
FROM
    "LiteLLM_SpendLogs"
WHERE
    "model_group" = $2
    AND "cache_hit" != 'True'
    AND "startTime" >= $3::timestamp
    AND "startTime" <= $4::timestamp
    AND (
        CASE
            WHEN $5 != 'null' THEN "api_key" = $5
            ELSE TRUE
        END
    )
    AND (
        CASE
            WHEN $6 != 'null' THEN "end_user" = $6
            ELSE TRUE
        END
    )
GROUP BY
    api_base
ORDER BY
    slow_count DESC;
    r:  r  r  r   )r]  r?   r0  r)  r   r-  r   r   r  r(  r  r!   r(  r  r	  r  r  )r  r  r  r  r  r	  r  r
	  r	  rowr	  s              rg   model_metrics_slow_responsesr!	  s(  s=      6!66	
 	
 '[08{2MX\\^i_.MMI'G 	11DD 	,+  /0IB &((22 K  	(C
+1rIY&%OOJ7:	'C
O		(
 !s   CDDADz/model/metrics/exceptionsz7View number of failed requests per model on config.yamlc                   K   t         t        dddt        j                        |xs% t	        j
                         t        t              z
  }|xs t	        j
                         }||dk(  rd}	 d}t         j                  j                  |||||       d {   }g }t               }		 ||D ]  }
|
j                  d	d
      }|
j                  dd      }|
j                  di       }||d}|j                  |       |j                  |       |j                         D ]  \  }}|	j                  |         |t!        |	      dS 7 w)Nr	  r  rw  ry  r  r	  r	  a?  
        WITH cte AS (
            SELECT
                CASE WHEN api_base = '' THEN litellm_model_name ELSE CONCAT(litellm_model_name, '-', api_base) END AS combined_model_api_base,
                exception_type,
                COUNT(*) AS num_rate_limit_exceptions
            FROM "LiteLLM_ErrorLogs"
            WHERE
                "startTime" >= $1::timestamp
                AND "endTime" <= $2::timestamp
                AND model_group = $3
            GROUP BY combined_model_api_base, exception_type
        )
        SELECT
            combined_model_api_base,
            COUNT(*) AS total_exceptions,
            json_object_agg(exception_type, num_rate_limit_exceptions) AS exception_counts
        FROM cte
        GROUP BY combined_model_api_base
        ORDER BY total_exceptions DESC
        LIMIT 200;
    combined_model_api_baser  total_exceptionsr   exception_counts)r9  r$	  )r  exception_types)r]  r?   r0  r)  r   r-  r   r   r  r	  r&  r  rJ  r  r  r~  r  )r  r  r  r  r  r	  r
	  r	  ri  r&	  rt  r9  r$	  r%	  curr_rowr  r  s                    rg   model_metrics_exceptionsr(	  (  sg      6!66	
 	
 MX\\^i_.MMI'G'[0I, &((229g'<g K HeO % 	'JNN#<bAE)~~.@!D)~~.@"E$4H OO,-OOH%(..0 '1##A&'	' o1FGG?s   BE
EB/E
c                 @   | j                  di       }t        |       }|i k(  r;| j                  di       }|j                  dd       }	 t        j                  |      }|i k(  rc| j                  di       }|j                  dd       }|j                  d      }t        |      dkD  r|d   }	 t        j                  ||d         }|j                         D ]  \  }}||vs|||<    || d<   t        | d	h
      } | S # t        $ r i }Y w xY w# t        $ r i }Y Uw xY w)Nr^  r  r  r9  r  r   r  re  r  deployment_dictr  )	r  r  rg  r  rp  r  rn  r  r   )r9  r^  r  r  r  r  r  r  s           rg   _get_proxy_model_infor,	  %)  sV   <,J 0e< R#3R8&**7D9	$!(!7!7m!L R#3R8&**7D9#))#.{a'OM	$!(!7!7#Q"
 #((* 1JJqM %E,1.G-HE L3  	$!#	$  	$!#	$s$   	C> -D >DDDDz/model/infoz/v1/model/infolitellm_model_idc           
      :  K   t         g	 t        t        t        j                  t                     }t        dt        t               |      }|j                         }t        |dh      }d|iS t        t        ddd	i
      t        t        dddi
      |Lt        j                  |      }|t        ddd| di
      t        |j                  d            }d|giS g }t        t               }t        g }n(t        j#                         }t        j%                         }t'        | ||      }	t)        | j*                  ||      }
t-        |	|
|t         t.        j1                  dd      t              }t3        |      dkD  rQg }|D ],  }t        j5                  |      }||j7                  |       . t        t9        j:                  |      }ng }|D ]  }t        |      } t=        j>                  d|       d|iS # t
        $ r i }Y w xY ww)a  
    Provides more info about each model in /models, including config.yaml descriptions (except api key and api base)

    Parameters:
        litellm_model_id: Optional[str] = None (this is the value of `x-litellm-model-id` returned in response headers)

        - When litellm_model_id is passed, it will return the info for that specific model
        - When litellm_model_id is not passed, it will return the info for all models

    Returns:
        Returns a dictionary containing information about each model.

    Example Response:
    ```json
    {
        "data": [
                    {
                        "model_name": "fake-openai-endpoint",
                        "litellm_params": {
                            "api_base": "https://exampleopenaiendpoint-production.up.railway.app/",
                            "model": "openai/fake"
                        },
                        "model_info": {
                            "id": "112f74fab24a7a5245d2ced3536dd8f5f9192c57ee6e332af0f0512e08bed5af",
                            "db_model": false
                        }
                    }
                ]
    }

    ```
    r  r   r  r  r*	  r  rx  r  zLLM Model List not loaded in. Make sure you passed models in your config.yaml or on the LiteLLM Admin UI. - https://docs.litellm.ai/docs/proxy/configsr  zLLM Router is not loaded in. Make sure you passed models in your config.yaml or on the LiteLLM Admin UI. - https://docs.litellm.ai/docs/proxy/configs)r  rd  zModel id = z not found on litellm proxyTr  )r  rh  rj  )rg  rh  rj  ri  F)rf  rg  rh  rY  ri  r  r   r  r  ) rY  r   r	   rg  r  rp  r   r   r  r   r  r'  r  get_deploymentr,	  rx   r  ro  rp  r   r   rg  r   r  r  rn  rf  r  rl  rm  r}   re  )r  r-	  r^  _deployment_info_deployment_info_dictdeployment_infors  rj  rh  rf  rg  all_models_str_relevant_modelsr9  router_modelsin_place_models                   rg   model_info_v1r7	  P)  s    ` 	#D'*@*@z*RSJ &)  "
 !1 ; ; = E145!
 -..  r
 	
   q
 	
 #$33=M3N"{+;*<<WX  !6!,,$,?!
 ./00J0;D0A%557(@@B+)/J
 "%11)/K
 -).223JERN >Q# 	7E&555GM( ''6	7 %'78JJ$ E.^DE /<Js  	J	s/   H(H	 E8H+AH	HHHHr3	  r  c           	         g }g }|D ]  }||vs|j                  |        |D ]e  }|||k7  r| j                  |      }|)|j                  t        di |j                                Ht        |g       }|j                  |       g t        j
                  +|D ]&  }|j                  t        j
                  v s d|_        ( |S )N)r  )r  	providersTr^  )r  get_model_group_infor  r  rg  public_model_groupsr  is_public_model_group)	r  r3	  r  model_groupsrx  r9  _model_group_infomodel_group_infomgs	            rg   _get_model_group_inforA	  )  s     /1LM (%  '(  2"{e';&;;;N( 3 U6G6R6R6T UV2!   012  "". 	0B~~!<!<<+/(	0 ri   z/model_group/infoc                   K   t         t        t         sdg iS ddlm}  || t        t        t
        t        t        ddddt               d{   }t        t        ||      }t        ||        d{   }d|iS 7 /7 
w)	a  
    Get information about all the deployments on litellm proxy, including config.yaml descriptions (except api key and api base)

    - /model_group/info returns all model groups. End users of proxy should use /model_group/info since those models will be used for /chat/completions, /embeddings, etc.
    - /model_group/info?model_group=rerank-english-v3.0 returns all model groups for a specific model group (`model_name` in config.yaml)



    Example Request (All Models):
    ```shell
    curl -X 'GET'     'http://localhost:4000/model_group/info'     -H 'accept: application/json'     -H 'x-api-key: sk-1234'
    ```

    Example Request (Specific Model Group):
    ```shell
    curl -X 'GET'     'http://localhost:4000/model_group/info?model_group=rerank-english-v3.0'     -H 'accept: application/json'     -H 'Authorization: Bearer sk-1234'
    ```

    Example Request (Specific Wildcard Model Group): (e.g. `model_name: openai/*` on config.yaml)
    ```shell
    curl -X 'GET'     'http://localhost:4000/model_group/info?model_group=openai/tts-1'
    -H 'accept: application/json'     -H 'Authorization: Bearersk-1234'
    ```

    Learn how to use and set wildcard models [here](https://docs.litellm.ai/docs/wildcard_routing)

    Example Response:
    ```json
        {
            "data": [
                {
                "model_group": "rerank-english-v3.0",
                "providers": [
                    "cohere"
                ],
                "max_input_tokens": null,
                "max_output_tokens": null,
                "input_cost_per_token": 0.0,
                "output_cost_per_token": 0.0,
                "mode": null,
                "tpm": null,
                "rpm": null,
                "supports_parallel_function_calling": false,
                "supports_vision": false,
                "supports_function_calling": false,
                "supported_openai_params": [
                    "stream",
                    "temperature",
                    "max_tokens",
                    "logit_bias",
                    "top_p",
                    "frequency_penalty",
                    "presence_penalty",
                    "stop",
                    "n",
                    "extra_headers"
                ]
                },
                {
                "model_group": "gpt-3.5-turbo",
                "providers": [
                    "openai"
                ],
                "max_input_tokens": 16385.0,
                "max_output_tokens": 4096.0,
                "input_cost_per_token": 1.5e-06,
                "output_cost_per_token": 2e-06,
                "mode": "chat",
                "tpm": null,
                "rpm": null,
                "supports_parallel_function_calling": false,
                "supports_vision": false,
                "supports_function_calling": true,
                "supported_openai_params": [
                    "frequency_penalty",
                    "logit_bias",
                    "logprobs",
                    "top_logprobs",
                    "max_tokens",
                    "max_completion_tokens",
                    "n",
                    "presence_penalty",
                    "seed",
                    "stop",
                    "stream",
                    "stream_options",
                    "temperature",
                    "top_p",
                    "tools",
                    "tool_choice",
                    "function_call",
                    "functions",
                    "max_retries",
                    "extra_headers",
                    "parallel_tool_calls",
                    "response_format"
                ]
                },
                {
                "model_group": "llava-hf",
                "providers": [
                    "openai"
                ],
                "max_input_tokens": null,
                "max_output_tokens": null,
                "input_cost_per_token": 0.0,
                "output_cost_per_token": 0.0,
                "mode": null,
                "tpm": null,
                "rpm": null,
                "supports_parallel_function_calling": false,
                "supports_vision": true,
                "supports_function_calling": false,
                "supported_openai_params": [
                    "frequency_penalty",
                    "logit_bias",
                    "logprobs",
                    "top_logprobs",
                    "max_tokens",
                    "max_completion_tokens",
                    "n",
                    "presence_penalty",
                    "seed",
                    "stop",
                    "stream",
                    "stream_options",
                    "temperature",
                    "top_p",
                    "tools",
                    "tool_choice",
                    "function_call",
                    "functions",
                    "max_retries",
                    "extra_headers",
                    "parallel_tool_calls",
                    "response_format"
                ]
                }
            ]
            }
    ```
    Nr  r   )rb  Frm  )r  r3	  r  )r=	  r  )r  r  r  rb  r  rY  r]  r  r  rA	  r   )r  r  rb  r3	  r=	  s        rg   r?	  r?	  *  s     D !3>|A 9+)#+$)!&$- N /Dn+/L
 6!+ L
 L!!/$s$   ABA=&B4A?5	B?Bz/model/settingszMReturns provider name, description, and required parameters for each providerc            	         K   g } t         j                  D ]2  }| j                  t        |t        j                  |                   4 | S w)a?  
    Used by UI to generate 'model add' page
    {
        field_name=field_name,
        field_type=allowed_args[field_name]["type"], # string/int
        field_description=field_info.description or "", # human-friendly description
        field_value=general_settings.get(field_name, None), # example value
    }
    rR  )r  fields)rg  provider_listr  ProviderInfoget_provider_fields)returned_listr  s     rg   model_settingsrI	  *  sQ     $ M)) 
22xP	

 s   A
Az/alerting/settingszFReturn the configurable alerting param, description, and current valuer  c                   K   	 t         't        ddt        j                  j                  i      | j
                  t        j                  k7  rAt        dddj                  t        j                  j                  | j
                        i      t         j                  j                  j                  ddi       d {   }|E|j                  9t        |j                        }|j                  di       }|j                  d	      }ni }d }d
did
did
did
did
did
did
did
did
did	}t         j"                  }|j$                  j'                         }g }d}	t(        j                  d	      r$t+        t(        d	   t,              rdt(        d	   v rd}	t/        d|d   d
   d|	|dndd d      }
|j1                  |
       t2        j4                  j7                         D ]m  \  }}||v sd }||v rd}nd}t/        |||   d
   |j8                  xs d|j                  |d       ||j:                  |dk(  rdnd      }
|j1                  |
       o |S 7 w)Nrd  r  r  {}, your role={}r  r  r  r  r  rV   BooleanInteger)	slack_alertingdaily_report_frequencyreport_check_intervalbudget_alert_ttloutage_alert_ttlregion_outage_alert_ttlminor_outage_alert_thresholdmajor_outage_alert_thresholdmax_outage_alert_list_sizeFr  TrN	  zhEnable slack alerting for monitoring proxy in production: llm outages, budgets, spend tracking failures.)
field_name
field_typefield_descriptionfield_valuestored_in_dbfield_default_valuepremium_fieldr  rS	  )r]  r'  r*   rn  r  r  r<   r  ru   not_allowed_accessr  r  r  r   r  r  r  r(  r  r  r  r  r  r/   r  r	  model_fieldsr  r  rj   )r  rM  db_general_settings_dictalerting_args_dictalerting_valuesallowed_args_slack_alerting_slack_alerting_args_dict
return_valis_slack_enabled_response_objrW	  
field_info_stored_in_dbs                 rg   alerting_settingsrk	  *  s     .EEKKL
 	

 ""&6&B&BB+22%88>>%//
 	
 !. 0 0 ? ? J J/0 !K !  &+>+J+J+V#'(;(G(G#H #;#?#?QS#T*B*F*Fz*R "9-#)9"5"()!4#Y/#Y/$*I#6)/(;)/(;'-y&9
L &7%N%NO / = = H H JJJ'J$d- &z22## 01&9 E$,8Te M m$"3"@"@"F"F"H -
J%,0M// $ %&%'
3F;","8"8">B599*dK*$.$6$6&*CCD
M m,'-( Is   B<I>I?D)I)A(Iz/queue/chat/completionsrb  )r  rY  r  c                    K   	 i }	 | j                          d {   }t        | j                        | j                  t	        |       j                         t        j
                  |      d|d<   t        j                  d|       t        j                  dd       xs t        xs |xs |j                  dd       |d<   |j                  dd       |j                  |j                  |d<   d|vri |d<   |j                  |d   d<   |j                  |d   d	<   t	        |       j                         }|j                  d
d        ||d   d<   t        |dd       |d   d<   |j                  |d   d<   t        |dd       |d   d<   t        |dd       |d   d<   t        |dd       |d   d<   t        | j                        |d   d<   t         r	t         |d<   t"        r	t"        |d<   t$        r	t$        |d<   t&        r	t&        |d<   t(        't+        ddt,        j.                  j0                  i      t)        j2                  d-i | d {   }d|v r |d   du rt5        t7        |||      d !      S |j8                  j;                  d"t        |d#         i       |S 7 7 V# t<        $ r}t>        jA                  |||$       d {  7   tC        |t*              rYtE        t        |d%d&t        |       d'      tF        jH                  t        |d(d)      t        |d*tJ        jL                        +      tC        |tD              r|tE        d,t        |      z   tF        jH                  t        |d(d)      tJ        jL                  +      d }~ww xY ww).N)r  rW   r%  r  proxy_server_requestzreceiving data: %scompletion_modelr9  r  r  user_api_keyuser_api_key_metadataauthorizationr%  r  user_api_key_aliasr  r  r  object_permission_id!user_api_key_object_permission_idteam_object_permission_id&user_api_key_team_object_permission_idri  rS  rT  rR  r:  rx  r  r  r  Tr  r  r  zx-litellm-prioritypriorityrs  r  Authentication Error(rK  r  rw  r#  ry  Authentication Error, r^  )'r  r  r  rW   r   rl  r}   re  r  r  rY  r  r  r  r  r  r`  ra  r  r_  r  r'  r*   r  r  schedule_acompletionr:  r  r%  rJ  rp  r  r|  r  r?   r>   
auth_errorr0  r  )r   r|  r9  r  r  _headersri  r  s           rg   async_queue_requestr~	  S+  s     Db
\\^# w{{#nn09>>@IIdO	(
#$ 	""#7>  !3T: ''' xx&	 	W 88FD!).?.G.G.S,44DLT!!D+<+D+DZ(4E4N4NZ01,W5::<T	
 '/Z#18{D2
Z-. 4E3L3LZ/03:y$4
Z/0 AH5tA
Z<= FM:DF
ZAB (+7;;'7Z$ "2D&:D"#!0D,D2C2Q2Q2W2W(X  $88@4@@ h4!7$$&7%!%
 /  	  '')=s4
CS?T(UV] $~ A   
66/ATX 7 
 	
 	
 a' 8/DSVHA-NO$//a&1Qv/J/JK	  >*G,s1v5 ++!Wf-,,	
 	

sd   NJ JH+J J'J .N/*J NJ J 	N(NKCNNN)r  r  c                    K   ddl m} t        t        | j                              }t        j                  d      }|j                  d      r|dz  }n|dz  }|ddlm	}  |t        d	      d
      S ddlm	}  |t        d	      d
      S w)z
    Create Proxy API Keys using Google Workspace SSO. Requires setting PROXY_BASE_URL in .env
    PROXY_BASE_URL should be the your deployed proxy endpoint, e.g. PROXY_BASE_URL="https://litellm-production-7002.up.railway.app/"
    Example:
    r   )ui_linkUI_USERNAMEr  zsso/callbackz/sso/callback)HTMLResponseF)show_deprecation_bannerr{  r$  r#  )litellm.proxy.proxy_serverr	  r   r  r  r  r  rd  fastapi.responsesr	  r   )r   r	  redirect_urlui_usernamer	  s        rg   fallback_loginr	  +  s      3 "#g&6&6"78L))M*KS!&' 	3'FTW
 	
 	3'FTW
 	
s   BBz/loginc                 P  K   ddl m}m} ddlm} | j                          d {   }t        |j                  d            }t        |j                  d            } |||t        t               d {   } ||t        t              }dd l}	|	j                  t        t        |      t        t        t              d	      }
 |t        | j                               }|j#                  d
      r|dz  }n|dz  }|dz  }t%        |d      }|j'                  d|
       |S 7 7 w)Nr   authenticate_usercreate_ui_token_objectr   usernamer   r	  r   rQ  r]  login_resultr  rB  HS256	algorithmr  ui//ui/?login=successi/  )r  r#  r  r  )litellm.proxy.auth.login_utilsr	  r	  r  r   formr  r  rQ  r]  r  rB  jwtencoder   r  r  rd  r9  
set_cookie)r   r	  r	  r   r	  r	  r   r	  returned_ui_token_objectr	  	jwt_tokenlitellm_dashboard_uiredirect_responses                rg   loginr	  +  s#    
 Y2D488J'(H488J'(H +#	 L  6!)!  

T+,S*  I *#g.>.>*?@$$S)%&,, )-AsS  WI >O  
s#   "D&D"AD&4D$5B.D&$D&z	/v2/loginc                 L  K   ddl m}m} ddlm} 	 | j                          d {   }t        |j                  d            }t        |j                  d            } |||t        t               d {   } ||t        t              }dd l}	|	j                  t        t        |      t        t        t              d	      }
 |t        | j                               }|j#                  d
      r|dz  }n|dz  }|dz  }t%        d|it&        j(                        }|j+                  d|
       |S 7 7 # t,        $ r}t/        j0                  dj3                  t        |                   t5        |t6              r|t5        |t8              rUt7        t;        |dt        |            t<        j>                  t;        |dd      t;        |dt&        j@                              t        |       }t7        |t<        j>                  dt&        j@                        d }~ww xY ww)Nr   r	  r	  r	  r   r	  r	  r	  r	  r  r	  r	  r	  r	  r	  r  r  z>litellm.proxy.proxy_server.login_v2(): Exception occurred - {}r  r  rw  r#  ry  )!r	  r	  r	  r  r   r  r  r  rQ  r]  r  rB  r	  r	  r   r  r  rd  r7  r0  HTTP_200_OKr	  rp  r}   r  ru   r  r?   r'  r  r>   r|	  r)  )r   r	  r	  r   r  r	  r   r	  r	  r	  r	  r	  json_responser  r  s                  rg   login_v2r	   ,  s    
 Y2=\\^#txx
+,txx
+,.!'	
 
 $:%-%$
  	JJ/0j!  
	  .c'2B2B.CD((- E)  F*  00$#%9:**
 	  WI >K $
D  &&LSSA	

 a(G=) 8SV4$//a&1Qv/T/TU	  q6(I !$//::	 #sM   H$D8 D3AD8 5D66B<D8 2H$3D8 6D8 8	H!CHH!!H$z	/v3/loginc                 z  K   ddl m}m} ddlm} 	 t
        j                  d      s+t        dt        j                  dt        j                        | j                          d {   }t        |j                  d            }t        |j                  d            } |||t        t        	       d {   } ||t
        t         
      }dd l}	|	j%                  t'        t(        |      t'        t        t              d      }
 |t        | j*                              }|j-                  d      r|dz  }n|dz  }|dz  }t/        j0                  d      }d| }|
|d}t2        !t2        j5                  ||d       d {    n t6        j5                  ||d       d {    t9        |ddt        j:                        S 7 `7 7 I7 *# t<        $ r}t?        j@                  djC                  t        |                   tE        |t              r|tE        |tF              rUt        tI        |dt        |            t        jJ                  tI        |dd      tI        |dt        jL                              t        |       }t        |t        jJ                  dt        jL                        d }~ww xY ww)Nr   r	  r	  r)  zH/v3/login is only available on workers with control_plane_url configuredry  r	  r   r	  r	  r	  r	  r  r	  r	  r	      login_code:r  r	  rn   )r  r  r  )r'  
expires_inr	  z>litellm.proxy.proxy_server.login_v3(): Exception occurred - {}r  r  rw  r#  )'r	  r	  r	  r  r   r  r  r?   r>   not_found_errorr0  HTTP_404_NOT_FOUNDr  r  rQ  r]  rB  r	  r	  r   r  r  rd  secretstoken_urlsafer  async_set_cacher  r7  r	  rp  r}   r  ru   r  r'  r  r|	  r)  )r   r	  r	  r   r  r	  r   r	  r	  r	  r	  r	  r'  r  cache_valuer  r  s                    rg   login_v3r	  h,  s    
 Y2P##$78 b$44)..	  \\^#txx
+,txx
+,.!'	
 
 $:%-%$
  	JJ/0j!  
	  .c'2B2B.CD((- E)  F*  00 $$R(!$(	 );OP(#33[b 4    %44[b 5    !4**
 	
[ $
B  &&LSSA	

 a(G=) 8SV4$//a&1Qv/T/TU	  q6(I !$//::	 #st   J;AG %G&AG 5G6CG G G "G#!G J;G G G G 	J8CJ33J88J;z/v3/login/exchangec                 L  K   	 t         j                  d      s+t        dt        j                  dt
        j                        | j                          d {   }|j                  d      }|s+t        dt        j                  dt
        j                        d| }t        t        j                  |       d {   }nt        j                  |       d {   }|rt        |t              s+t        dt        j                  dt
        j                        t        t        j!                  |       d {    nt        j!                  |       d {    t#        |d	   |d
   dt
        j$                        }|j'                  d	|d	          |S 7 G7 7 7 f7 I# t        $ r  t(        $ rf}t+        j,                  dj/                  t1        |                   t        t1        |      t        j                  dt
        j2                        d }~ww xY ww)Nr)  zQ/v3/login/exchange is only available on workers with control_plane_url configuredry  r'  zMissing 'code' parameterr	  r  zInvalid or expired login coder  r	  r	  r	  r  zGlitellm.proxy.proxy_server.login_v3_exchange(): Exception occurred - {}rw  )r  r  r?   r>   r	  r0  r	  r  r|	  r  r  r  r  r  r  HTTP_401_UNAUTHORIZEDasync_delete_cacher7  r	  r	  rp  r}   r  ru   r  r)  )r   r  r'  r  cached_datar	  r  s          rg   login_v3_exchanger	  ,  s    =
##$78 k$44)..	  \\^#xx 2$//00	  "$(	( 1 A Ai A PPK 2 B By B QQK*[$"? 7$//11	  (#6696EEE$77I7FFF$$W- +N ; **
 	  WK4H IM $ QQ FF   
&&U\\A	

 F ++66	
 	

s   H$AF) FA&F) >F!?F) F#A F) >F%?F) F'?F) H$F) !F) #F) %F) 'F) )H!;A!HH!!H$z/onboarding/get_tokeninvite_linkc                 T  K   ddl m} t        +t        dt        j
                  dt        j                        t        't        ddt        j                  j                  i	      t        j                  j                  j                  d
| i       d{   }|t        dddi	      t         j"                  j%                         j'                         }|j(                  j'                         }||k  rt        dddi	      |j*                  du rt        dddi	      t        j                  j,                  j                  d|j.                  i       d{   }|t        dddi	      |j0                  }t3        d#ddi|j4                  t6        t         j8                  g i i d|j.                  dd	 d{   }|d   }	t;        t=        |j>                              }
|
jA                  d      r|
dz  }
n|
dz  }
ddl!}tE               } ||j.                  |	|j0                  |j4                  dtF        tH        jK                  dd      |tM               	      }|jO                  tQ        tR        |      t        d       }|
d!jU                  ||      z  }
|
||d"S 7 
7 G7 w)$z
    - Get the invite link
    - Validate it's still 'valid'
    - Invalidate the link (prevents abuse)
    - Get user from db
    - Pass in user_email if set
    r   )ReturnedUITokenObjectNzMaster Key not set for Proxy. Please set Master Key to use Admin UI. Set `LITELLM_MASTER_KEY` in .env or set general_settings:master_key in config.yaml.  https://docs.litellm.ai/docs/proxy/virtual_keys. If set, use `--detailed_debug` to debug issue.rQ  ry  rx  r  r  r{  r    %Invitation link does not exist in db.Invitation link has expired.T&Invitation link has already been used.r  User does not exist in db.r  r  zlitellm-dashboard)	r  r  key_max_budgetrv  r  r~  r  r  r  r  r  zui/onboardingz/ui/onboardingusername_passwordlitellm_key_header_nameAuthorization)	r  r  
user_emailr  login_methodrB  auth_header_name(disabled_non_admin_personal_key_creationr  r	  r	  z?token={}&user_email={})	login_urlr  r	  r^  )+litellm.types.proxy.ui_ssor	  rQ  r?   r>   r|	  r0  r)  r]  r'  r*   rn  r  r  litellm_invitationlinkr  rg  r  get_utc_datetimer	  
expires_atis_acceptedrw  r  r	  r   r  r%   max_ui_session_budgetr   r  r  rd  r	  r   rB  r  r  r   r	  r   r  ru   )r	  r   r	  
invite_objutc_now_dateexpires_at_dateuser_objr	  ri  r  r	  r	  r	  r	  r	  s                  rg   
onboardingr	  -  s     A P ++66	
 	
 .EEKKL
 	

 %''>>JJ[! K  J W.U$V
 	

 ==11388:L ++002O%W.L$M
 	

 %EF
 	
 #%%77CC*,,- D  H W.J$K
 	
 $$J+  "++3%;;''*

 H 7
C)#g.>.>*?@$$S)/ 00 	56 -  5  &&$$(!)--%
 2Z-/  

T+,  I 5<<Y
SS)  e0s9   BJ(J CJ(J#A!J(>J&?C"J(#J(&J(z/onboarding/claim_tokenr  c                   K   t         't        ddt        j                  j                  i      t         j
                  j                  j                  d| j                  i       d{   }|t        dddi      t        j                  j                         j                         }|j                  j                         }||k  rt        ddd	i      |j                  d
u rt        dddi      |j                  | j                  k7  r3t        dddj!                  | j                  |j                        i      t#        | j$                        }t         j
                  j&                  j)                  d|j                  id|i       d{   }|t        dddi      t        j                  j                         }t         j
                  j                  j)                  d| j                  i||d
|j                  d       d{    |r(t+        |d      r|j,                  j/                  dd       |S 7 7 7 5w)a&  
    Special route. Allows UI link share user to update their password.

    - Get the invite link
    - Validate it's still 'valid'
    - Check if user within initial session (prevents abuse)
    - Get user from db
    - Update user password

    This route can only update user password.
    Nrx  r  r  r{  r  r	  r	  r	  Tr	  zwInvalid invitation link. The user id submitted does not match the user id this link is attached to. Got={}, Expected={}r  r   r  r	  )accepted_atr  r	  r  __dict__)r]  r'  r*   rn  r  r  r	  r  invitation_linkrg  r  r	  r	  r	  r	  r  ru   r   r   rw  rJ  r  r	  r  )r  r	  r	  r	  	hashed_pwr	  r  s          rg   claim_onboarding_linkr	  z-  s_     .EEKKL
 	

 %''>>JJT))* K  J W.U$V
 	

 ==11388:L ++002O%W.L$M
 	

 %EF
 	
 T\\)  S  Z  ZLL*"4"4
 	
 dmm,I"%%77>>*,,-Z4K ?  H W.J$K
 	

 ==113L



1
1
8
8T))*'&$,,	
 9    GHj1j$/OuFs8   A'I)I*D)IIA<II1IIIz/get_logo_urlc                  6    t        j                  dd      } d| iS )z)Get the current logo URL from environmentUI_LOGO_PATHr  logo_url)r  r  )	logo_paths    rg   get_logo_urlr	  -  s     		."-I	""ri   z
/get_imagec                    K   t         j                  j                  t         j                  j                  t                    } t         j                  j                  | d      }t        j                  dd      j                         dk(  }|rdn| }t        j                  d|      }t         j                  j                  |      s0	 t        j                  |d       t        j                  d	|        || k7  r t         j                  j                  |d      n|}|| k7  r!t         j                  j                  |      s|}t        j                  |t         j                         r|n| }t         j                  j                  |d      }t        j                  d|      }	t        j                  d|	       |	|k7  rX|	j#                  d      sGt         j                  j                  |	      rt%        |	d      S t        j                  d|	 d       |}	t         j                  j                  |      rt%        |d      S |	j#                  d      r	 ddlm}
 ddlm}  |
|j.                  ddi      }|j1                  |	       d{   }|j2                  dk(  r=t5        |d      5 }|j7                  |j8                         ddd       t%        |d      S t%        |d      S t%        |	d      S # t        t        f$ r)}t        j                  d
| d| d       | }Y d}~0d}~ww xY w7 # 1 sw Y   mxY w# t:        $ r2}t        j                  d|	 d|        t%        |d      cY d}~S d}~ww xY ww)zGet logo to show on admin UIzlogo.jpgrQ  r  rR  z/var/lib/litellm/assetsLITELLM_ASSETS_PATHTrJ  zCreated assets directory at z"Cannot create assets directory at r\   z@. Logo caching may not work. Using current directory for assets.Nzcached_logo.jpgr	  zReading logo from path: %szhttp://r  z
image/jpegrw	  zUI_LOGO_PATH 'z.' does not exist, falling back to default logor   get_async_httpx_clienthttpxSpecialProvidertimeout      @llm_providerr  r{  wbzError downloading logo from )r  rX   r  r  __file__r:  r  r  r9  rM  r}   re  rA  rB  r|  accessW_OKr@  r6  &litellm.llms.custom_httpx.http_handlerr	  litellm.types.llms.custom_httpr	  UIr  r#  r   r_   r$  rp  )r|  default_site_logois_non_rootdefault_assets_dir
assets_dirr  default_logo	cache_dir
cache_pathr	  r	  r	  async_clientri  fs                  rg   	get_imager	  -  s    
 ''//"''//(";<K[*=)).399;vEK 7B2{02DEJ 77>>*%	%KK
T2 &&)Ej\'RS $ 	Z, 
 [ )E( ii
BGG<
+Ii):;J		.,7I;YG L )=)=>U)V77>>)$	lCC$$YK'UV	
 !	 
ww~~j!J<@@ 34	GUK1144!3'L *--i88H##s**d+ .qGGH,,-. $J<HH $L\JJ I,??A  ) 	% ((4ZL1# FQ R %J	%^ 9. .  	G &&)Ei[PRSTRU'VWFF	Gs   CM9/K2 5EM96L; L-L; 'L/L; M9L; $M92L*L%M9%L**M9-L; /L84L; ;	M6'M1+M6,M91M66M9z/get_faviconc                    K   ddl m}  t        j                  j	                  t        j                  j                  t                    }t        j                  j                  |ddd      }t        j                  dd      }|s9t        j                  j                  |      rt        |d	      S t        d
d      |j                  d      r	 ddlm} ddlm}  ||j"                  ddi      }|j%                  |       d{   }|j&                  dk(  r0|j(                  j%                  dd      } | |j*                  |      S t-        j.                  d||j&                         t        j                  j                  |      rt        |d	      S t        d
d      t        j                  j                  |      rt        |d	      S t        j                  j                  |      rt        |d	      S t        d
d      7 # t        $ r  t0        $ rZ}	t-        j2                  d||	       t        j                  j                  |      rt        |d	      cY d}	~	S t        d
d      d}	~	ww xY ww)z$Get custom favicon for the admin UI.r   r+  r,  r-  zfavicon.icoLITELLM_FAVICON_URLr  zimage/x-iconrw	  rx  zDefault favicon not foundr  r	  r	  r	  r	  r	  r	  Nr{  content-type)r$  r  z*Failed to fetch favicon from %s: status %szFavicon not foundz%Error downloading favicon from %s: %s)r	  r+  r  rX   r  r  r	  r:  r  r9  r6  r'  r@  r	  r	  r	  r	  r	  r  r#  r%  r$  r}   r|  rp  re  )
r+  r|  default_faviconfavicon_urlr	  r	  r	  ri  content_typer  s
             rg   get_faviconr
  *.  s     +''//"''//(";<Kggll;VO))126K77>>/*NKK4OPP56 	MUK1144!3'L *--k::H##s*'//33NNS$,,+ 
 %,,@((
 77>>/2'NSS#<OPP 77>>+&GG77>>/*NKK4GHH= ;   	 	M &&7a ww~~o.#OOOC8KLL	Msj   CI96H
 HAH
 I9AH
 I9H
 "A%I9H
 
I6AI1I6I9$I11I66I9z/invitation/newzInvite Links)r  rY  rM  r  c                   K   	 ddl m} t        't        ddt        j
                  j                  i      |j                  t        j                  k(  xs# t        |t        t        t               d{   }|sAt        dddj                  t        j                  j                  |j                        i      |j                  t        j                  k7  r?t        | j                   |t        t        t        	       d{   }|st        ddd
i       || |       d{   }|S 7 7 +7 
# t"        $ r}t%        |      d}~ww xY ww)%  
    Allow admin to create invite links, to onboard new users to Admin UI.

    ```
    curl -X POST 'http://localhost:4000/invitation/new'         -H 'Content-Type: application/json'         -d '{
            "user_id": "1234" // 👈 id of user in 'LiteLLM_UserTable'
        }'
    ```
    r   )create_invitation_for_userNrd  r  r  re  rK	  )target_user_idr  r]  r  r  zGYou can only create invitations for users in your organization or team.)r  r  )0litellm.proxy.management_helpers.user_invitationr
  r]  r'  r*   rn  r  r  r<   r  r   r  r  ru   r^	  r   r  rp  r   )r  r  r
  
has_access
can_inviteri  r  s          rg   new_invitationr

  f.  s_    *9+	
  !2!I!I!O!OP  ''+;+G+GG /"3+#5"3	  	 /66)<<BB)33  &&*:*F*FF4#||"3+#5"3  J # #!j  4/
 
 O(

  +'**+s`   EA0D2 4D,5BD2 D."D2 %D0&D2 +E,D2 .D2 0D2 2	E;EEEz/invitation/infoinvitation_idc                   K   t         't        ddt        j                  j                  i      |j
                  t        j                  k7  rAt        dddj                  t        j                  j                  |j
                        i      t         j                  j                  j                  d| i       d{   }|t        dddi      |S 7 w)	r
  Nrd  r  r  rK	  r{  r  -Invitation id does not exist in the database.)r]  r'  r*   rn  r  r  r<   r  ru   r^	  r  r	  r  )r
  r  ri  s      rg   invitation_infor
  .  s     . .EEKKL
 	

 ""&6&B&BB+22%88>>%//
 	
 #%%<<HH]# I  H LM
 	
 Os   B;C=C>Cz/invitation/updatec           	        K   t         't        ddt        j                  j                  i      |j
                  (t        dddj                  |j
                        i      t        j                  j                         }t         j                  j                  j                  d| j                  i| j                  | j                  |||j
                  d	       d{   }|t        ddd
i      |S 7 w)uV  
    Update when invitation is accepted

    ```
    curl -X POST 'http://localhost:4000/invitation/update'         -H 'Content-Type: application/json'         -d '{
            "invitation_id": "1234" // 👈 id of invitation in 'LiteLLM_InvitationTable'
            "is_accepted": True // when invitation is accepted
        }'
    ```
    Nrd  r  r  rx  z'Unable to identify user id. Received={}r{  )r{  r	  r	  r  r  r  r
  )r]  r'  r*   rn  r  r  ru   rg  r  r	  r  r	  rJ  r
  r	  )r  r  r  ri  s       rg   invitation_updater
  .  s    2 .EEKKL
 	

   (BII%--
 	
 ==113L"%%<<CCT''($$++'&+33
 D 	 	H LM
 	
 O!	s   CC: C8!C:z/invitation/deletec                   K   t         't        ddt        j                  j                  i      |j
                  t        j                  k(  }t        |t         t        t               d{   }|sC|sAt        dddj                  t        j                  j                  |j
                        i      |ry|swt         j                  j                  j                  d| j                   i       d{   }|t        ddd	i      |j"                  |j$                  k7  rt        d
ddi      t         j                  j                  j'                  d| j                   i       d{   }|t        ddd	i      |S 7 7 7 w)u  
    Delete invitation link

    ```
    curl -X POST 'http://localhost:4000/invitation/delete'         -H 'Content-Type: application/json'         -d '{
            "invitation_id": "1234" // 👈 id of invitation in 'LiteLLM_InvitationTable'
        }'
    ```
    Nrd  r  r  re  rK	  r{  r  r
    z=Organization admins can only delete invitations they created.)r]  r'  r*   rn  r  r  r<   r  r   r  r  ru   r^	  r  r	  r  r
  r  r  delete)r  r  is_proxy_adminis_other_admin
invitationri  s         rg   invitation_deleter
  (/  s    0 .EEKKL
 	
 '004D4P4PPN5+#-+	 N .+22%88>>%//
 	
 n(++BBNN++, O 
 

 !PQ    $5$=$==\  #%%<<CCT''( D  H LM
 	
 O[(
 s8   A)F+F,BF2F3A6F)F*FFFz/config/updatezconfig.yamlconfig_infoc                 x  K   	 |j                   t        j                  k7  rt        dd      ddl}	 t
        t        d      t        durt        dd	d
i      | j                  d      }t
        j                  |      }|j                         D ]H  \  }}|dk(  st
        j                  j                  j                  d|i||dd|id       d{    J t        j                          d{   }t!        j"                  d|       | j$                  |j'                  di        | j$                  j)                  d      }|d   }|j                         D ]G  \  }}|dk(  r8d|vrddgi}n.t+        |d   t,              rd|d   vr|d   j/                  d       |||<   I ||d<   | j0                  l|j'                  di        | j0                  }	|	j                         D ]  \  }}t3        |      }
|
|	|<    |d   }|	j                         D ]  \  }}|	|   ||<    | j4                  |j'                  di        | j4                  }i ||d   |d<   d|v red|d   v r^t+        |d   d   t,              rHt+        |d   t,              r5t7        |d         }|d   d   |z   }t-        t9        |            }||d   d<   t        j;                  |       d{    t        j=                  t
        t>               d{    ddiS 7 77 7 57 # t        $ r}t!        j@                  djC                  tE        |                   t!        j"                  tG        jH                                t+        |t              rYtK        tM        |d d!tE        |       d"      tN        jP                  tM        |d#d$      tM        |d%tR        jT                        &      t+        |tJ              r|tK        d'tE        |      z   tN        jP                  tM        |d#d$      tR        jT                  &      d}~ww xY ww)(z
    For Admin UI - allows admin to update config via UI

    Currently supports modifying General Settings + LiteLLM settings
    r
  z#Only proxy admins can update configr  r   NzNo DB ConnectedTrx  r  CSet `'STORE_MODEL_IN_DB='True'` in your env to enable this feature.r  r  r  r  r   r  r  zLoaded config: %sr  r  r  r  r  r  r  rl  r  r  r`   zConfig updated successfullyzBlitellm.proxy.proxy_server.update_config(): Exception occured - {}r  ry	  rK  r  rw  r#  ry  rz	  )+r  r<   r  r'  r  r]  rp  r  r  jsonify_objectr  r  r  r  r  r  r}   re  r  ra  r  r  r  r  r  r   r  rG   r&  r  rz  r  r  ru   r  r  r  r?   r  r>   r|	  r0  r  )r
  r  r  updated_settingsr  r  r~  updated_general_settings_existing_settings_updated_environment_variablesr  _existing_env_variablesupdated_litellm_settings$updated_success_callbacks_normalizedcombined_success_callbackr  s                   rg   update_configr%
  y/  s    D
&&*:*F*FFC8]^^	  -..D(b  '+++>(778HI$**, 	DAq%%#&&55<<'+121"E#0!"4 =   	 $..00""#6? ''30"5'2'C'C'H'H! (I ($ "((:!;0668 	*1..!);;.87)-D*#$6z$BDI"*<Z*HH.z:AA'J()"1%	* *<F%&,,85r:-8-N-N* 7<<> D1"6Q"?4C.q1D '--D&E#6<<> O1-KA-N'*O
 ''30"5'2'C'C$***+,*F%& #&>>&&1C*DD -./ABD !9:L!MtT;S01CD<8 123EF>? . 15S9R5S0T- 2 -.*
 &&&&999))';L * 
 	
 	
 899m 1J 	:	

  
""PWWA	

 	""9#7#7#9:a' 8/DSVHA-NO$//a&1Qv/J/JK	  >*G,s1v5 ++!Wf-,,	
 	
!
sy   P:BL 8L LL 4L5G(L L&L LL P:L L L L 
P7!DP22P77P:z/config/field/updatec           
        K   	 t         't        ddt        j                  j                  i      |j
                  t        j                  k7  r't        ddt        j                  j                  i      | j                  t        j                  vr(t        dddj                  | j                        i      	 t        di | j                  | j                  i t         j                   j"                  j%                  ddi	       d{   }||j&                  i }nt)        |j&                        }| j                  || j                  <   t         j                   j"                  j+                  ddidt-        j.                  |      d
dt-        j.                  |      id       d{   }|S # t        $ r2 t        dddj                  t        | j                              i      w xY w7 7 Fw)z=
    Update a specific field in litellm general settings
    Nrd  r  r  Invalid field={} passed in.z)Invalid type of field value={} passed in.r  r  r  r  r   r  r  r^  )r]  r'  r*   rn  r  r  r<   r  r^	  rW	  r.   r_	  ru   rZ	  rp  rV   r  r  r  r   r  r  r  rF  r  r  rM  r  ri  s        rg   update_config_general_settingsr)
  0  s     .EEKKL
 	

 ""&6&B&BB.AAGGH
 	

 3@@@:AA$//RS
 	



D$2B2B CD !. 0 0 ? ? J J/0 !K ! 
 "&9&E&E&M 3 ? ?@ )-(8(8T__%"%%44;;/0%7

ScHde$djj1A&BC
 <  H OC  
DKK))*
 	

s=   B7G5:!F3 /G5
G1B!G5,G3-G53;G..G53G5z/config/field/inforW	  c                   K   	 t         't        ddt        j                  j                  i      |j
                  t        j                  k7  r't        ddt        j                  j                  i      | t        j                  vrt        dddj                  |       i      t         j                  j                  j                  ddi       d {   }||j                  t        dddj                  |       i      t!        |j                        }| |v rt#        | ||    	      S t        dddj                  |       i      7 ww)
Nrd  r  r  r'
  r  r  r  zField name={} not in DB)rW	  rZ	  )r]  r'  r*   rn  r  r  r<   r  r^	  r.   r_	  ru   r  r  r  r   r  r,   )rW	  r  rM  r  s       rg   get_config_general_settingsr+
  d0  st    
 .EEKKL
 	

 ""&6&B&BB.AAGGH
 	

 .;;;:AA*MN
 	
 !. 0 0 ? ? J J/0 !K ! 
 "&9&E&E&M6==jIJ
 	

   3 ? ?@))"%3CJ3O   !:!A!A*!MN %s   CEEA8Ez/config/listr  c                   K   	 t         't        ddt        j                  j                  i      |j
                  t        j                  k7  rAt        dddj                  t        j                  j                  |j
                        i      t         j                  j                  j                  ddi       d{   }|"|j                  t        |j                        }ni }d	d
id	d
id	d
id	d
id	did	did	did	did	did	did	did	did	did}g }t        j                   j#                         D ]  \  }}||v s||   d	   }|dk(  r/|dk(  rt$        g}	ng }	|	D ]  }
|
j&                  j#                         D cg c]3  \  }}t)        ||j*                  dt,        j/                  |d      d      5 }}}d}|
j                   j#                         D ]6  \  }}t1        |d      r |j2                  |j2                  ||   _        |dz  }8 d}||v rd}n
|t,        v rd}t7        |||   d	   |j2                  xs dt,        j/                  |d      ||j8                  |      }|j;                  |        Id}d}||v rd}n
|t,        v rd}t,        j/                  |d      }|	||v r||   }t7        |||   d	   |j2                  xs d|||j8                  |      }|j;                  |        |S 7 :c c}}w w)z
    List the available fields + current values for a given type of setting (currently just 'general_settings'user_api_key_dict: UserAPIKeyAuth = Depends(user_api_key_auth),)
    Nrd  r  r  rK	  r  r  r  rV   rM	  PydanticModelrL	  Stringr
   )rO  rP  max_request_size_mbmax_response_size_mbr.  r  rQ  r/  mcp_internal_ip_rangesmcp_trusted_proxy_rangesalways_include_stream_usage!forward_client_headers_to_llm_apimcp_required_fieldsr.  r  )rW	  rX	  rY	  r\	  r[	  r   r  r  TF)rW	  rX	  rY	  rZ	  r[	  r\	  nested_fields)r]  r'  r*   rn  r  r  r<   r  ru   r^	  r  r  r  r   r  r.   r_	  r  r=   rC  r2   r^   r  r  r  r  rY	  r/   rj   r  )r  r  rM  r`	  rc	  rf	  rW	  ri	  typed_dict_typepydantic_class_listpydantic_class	sub_fieldsub_field_typer6
  rp  sub_field_inforj	  rh	  _field_values                      rg   get_config_listr>
  0  s     
 .EEKKL
 	

 ""&6&B&BB+22%88>>%//
 	
 !. 0 0 ? ? J J/0 !K !  &+>+J+J+V#'(;(G(G#H #%  #))!4)/(; &	2!' 3#)?";$i0(.	':06/A#)6"2%+V$4(.	':.4i-@ &/L  J"7"D"D"J"J"L N1
J% +:6v>O/1!99+E*F'*,'&9 *5N :H9W9W9]9]9_	% 6I~ $'0'5'>'>.00@0D0DYPT0U)-	%M 	% C (44::<! !& $NMB . : : F 3A2L2L * #/q! %)M!%==(,#'77(-$.#-#/
#;F#C*4*@*@*FB$4$8$8T$J%2,6,>,>&3%M %%m4U*5Z !% $!99$(M#33$)M/33JE'J:R,R#;J#GL *)+J7?&0&<&<&B ,!.(2(:(:"/! !!-0]N1` WR	%s-   B<L>K8?A?L?A L?8K;
7EL;Lz/config/field/deletec                   K   	 t         't        ddt        j                  j                  i      |j
                  t        j                  k7  rAt        dddj                  t        j                  j                  |j
                        i      | j                  t        j                  vr(t        dddj                  | j                        i      t         j                  j                  j                  ddi	       d{   }||j                   (t        ddd
j                  | j                        i      t#        |j                         }|j%                  | j                  d       t         j                  j                  j'                  ddidt)        j*                  |      ddt)        j*                  |      id       d{   }|S 7 7 w)z|
    Delete the db value of this field in litellm general settings. Resets it to it's initial default value on litellm.
    Nrd  r  r  rK	  r'
  r  r  r  zField name={} not in configr  r   r  r  )r]  r'  r*   rn  r  r  r<   r  ru   r^	  rW	  r.   r_	  r  r  r  r   r  r  r  r  rF  r(
  s        rg   delete_config_general_settingsr@
  71  s    
 .EEKKL
 	

 ""&6&B&BB+22%88>>%//
 	
 3@@@:AA$//RS
 	
 !. 0 0 ? ? J J/0 !K ! 
 "&9&E&E&M:AA$//RS
 	

   3 ? ?@ $/"%%44;;/0%7

ScHde$djj1A&BC
 <  H O3"s%   D GGC	GGGGz/config/callback/deletec                   K   t         't        ddt        j                  j                  i      |j
                  t        j                  k7  rAt        dddj                  t        j                  j                  |j
                        i      t        durt        dddi      	 t        j                          d{   }| j                  j                         }|j                  d	i       }|j                  d
g       }||vrt        ddd| di      |j!                  |       ||j#                  d	i       d
<   t        j%                  |       d{    t        j'                  t         t(               d{    d| ||t+        j,                         j/                         dS 7 7 W7 2# t        $ r  t0        $ r}t3        j4                  dt7        |              t3        j8                  t;        j<                                t?        dt7        |      z   t@        jB                  dtD        jF                        d}~ww xY ww)z>
    Delete specific logging callback from configuration.
    Nrd  r  r  rK	  Trx  r
  r  rl  rx  z
Callback 'z#' not found in active configurationr
  r  zSuccessfully deleted callback: )r`   removed_callbackremaining_callbacks
deleted_atzClitellm.proxy.proxy_server.delete_callback(): Exception occurred - zError deleting callback: callback_namery  )$r]  r'  r*   rn  r  r  r<   r  ru   r^	  r  r  r  rE
  r  r  removera  r  rz  r  r   r-  r  rp  r}   r  r  re  r  r  r?   r>   internal_server_errorr0  r)  )r  r  r~  rE
  r  r  r  s          rg   delete_callbackrH
  1  s\     .EEKKL
 	

 ""&6&B&BB+22%88>>%//
 	
 $^
 	
2
#..00**002 "::&8"=,001CRH 11z-8[\  	  /  	,b1	

 &&&&999 ))';L * 
 	
 	

 9H -#4",,.224	
 	
; 1, 	:	
   

""QRUVWRXQYZ	
 	""9#7#7#9:/#a&8 66!66	
 	


sb   B#I&F2 =F,>BF2 F.&F2 =F0>-F2 +I,F2 .F2 0F2 2IA?IIIz/get/config/callbacks)r  r  rY  c                    K   	 ddl } t               }t        j                          d{   }|j	                  di       }|j	                  di       }|j	                  di       }|j	                  dg       }|j	                  dg       }|j	                  dg       }d	 }	 |	|      } |	|      } |	|      }g }
	 |D ]  }|
j                  t        |d
|               |D ]  }|
j                  t        |d|               |D ]  }|
j                  t        |d|               |j	                  dg       }g }d|v rdg}i }|D ]D  }|j	                  |d      }|t        j                  dd      }|||<   3t        ||      }|||<   F t        j                  j                  }t        j                  j                         }t        j                  j                  }|j                  d|||d       g d}i }|D ].  }|j	                  |d      }|d||<   t        ||      }|||<   0 |j                  d|d       t        i }nt        j!                         }d
|
|||dS 7 8# t"        $ r}t%        j&                  dj)                  t+        |                   t-        |t.              rYt1        t3        |ddt+        |       d      t4        j6                  t3        |dd      t3        |dt8        j:                              t-        |t0              r|t1        dt+        |      z   t4        j6                  t3        |dd      t8        j:                        d}~ww xY ww)z~
    For Admin UI - allows admin to view config via UI
    # return the callbacks and the env variables for the callback

    r   Nr  r  r  rl  r  r  c                 4    t        | t              r| gS | g S | S rP  )r  r  )rn  s    rg   normalize_callbackz&get_config.<locals>.normalize_callback1  s$    (C( z!!	Ori   r  r  success_and_failurer  r  SLACK_WEBHOOK_URLr/  )r  	variablesactive_alertsalerts_to_webhook)	SMTP_HOST	SMTP_PORTSMTP_USERNAMESMTP_PASSWORDSMTP_SENDER_EMAILTEST_EMAIL_ADDRESSEMAIL_LOGO_URLEMAIL_SUPPORT_CONTACTemail)r  rN
  )r0  r  alertsr  available_callbacksz?litellm.proxy.proxy_server.get_config(): Exception occured - {}r  ry	  rK  r  rw  r#  ry  rz	  )r  AllCallbacksr  r  r  r  rH   r  r  r   r  r(  r  _all_possible_alert_typesr  r  get_settingsrp  r}   r  ru   r  r  r'  r?   r  r>   r|	  r0  r  )r  all_available_callbacksr  r  r)  r  _success_callbacks_failure_callbacks_success_and_failure_callbacksrK
  _data_to_return	_callback	_alertingalerting_data_slack_vars_slack_env_vars_varenv_variabler  _decrypted_value_alerting_types_all_alert_types_alerts_to_webhook_email_vars_email_env_vars_router_settingsr  s                              rg   r  r  1  s    \
"..(3355'OO,>C'OO,>C +0G L.223ErJ.223ErJ):)>)>{B)O&	 00BC/0BC);**
& 	 , 	I"" I7LM	
 , 	I"" I7LM	
 8 	I"" 46K	 &))*b9	i#K !O# 
=488tD'YY':DAF,2OD) (<*($ -=OD)
= 0GGSSO!99SSU  "99NN    #!0%4);		
  	9D044T4@L#(,% $8lPT#U (8%	9 	,	
 !)668  (#/#:
 	
y 6F  
&&MTTA	

 a' 8/DSVHA-NO$//a&1Qv/J/JK	  >*G,s1v5 ++!Wf-,,	
 	

s:   M%I$ I!H6I$  M!I$ $	M-C*MMMz/config/yamlc                    K   ddiS w)a  
    This is a mock endpoint, to show what you can set in config.yaml details in the Swagger UI.

    Parameters:

    The config.yaml object has the following attributes:
    - **model_list**: *Optional[List[ModelParams]]* - A list of supported models on the server, along with model-specific configurations. ModelParams includes "model_name" (name of the model), "litellm_params" (litellm-specific parameters for the model), and "model_info" (additional info about the model such as id, mode, cost per token, etc).

    - **litellm_settings**: *Optional[dict]*: Settings for the litellm module. You can specify multiple properties like "drop_params", "set_verbose", "api_base", "cache".

    - **general_settings**: *Optional[ConfigGeneralSettings]*: General settings for the server like "completion_model" (default model for chat completion calls), "use_azure_key_vault" (option to load keys from azure key vault), "master_key" (key required for all calls to proxy), and others.

    Please, refer to each class's description for a better understanding of the specific attributes within them.

    Note: This is a mock endpoint primarily meant for demonstration purposes, and does not actually provide or change any configurations.
    helloworldr^  )r
  s    rg   config_yaml_endpointru
  2  s     . Ws   z/reload/model_cost_mapc           
        K   | j                   t        j                  k7  rt        dd| j                          	 t        t        dd      ddlm} t        j                  } ||	      }|t        _	        t                t        j                  |
       t        j                         }|j                         at        j                   j"                  j%                  ddi       d{   }d}|r'|j&                  r|j&                  j)                  d      }t        j                   j"                  j+                  ddidt-        ddd      ddt-        |dd      id       d{    |rt/        |      nd}t1        j2                  d|        d| dd||j                         dS 7 7 F# t4        $ r?}t1        j6                  dt9        |              t        ddt9        |             d}~ww xY ww)z
    ADMIN ONLY / MASTER KEY Only Endpoint

    Manually reload the model cost map from the remote source.
    This will fetch fresh pricing data from the model_prices_and_context_window.json file.
    r
  2Access denied. Admin role required. Current role: r  Nrx  !Database connection not availabler   r  r  r  r  r  r  r  Tr  r  r   r  r  zCModel cost map reloaded successfully in current pod. Models count: z"Price data reloaded successfully! z models updated.r  )r`   r0  models_count	timestampz!Failed to reload model cost map: )r  r<   r  r'  r]  r  r  rg  r  r  rO   r  r   r  r  r  r  r  r  r   r  r  r'   rn  r}   rd  rp  r  r  )	r  r  r  r  r  existing_configexisting_intervalry
  r  s	            rg   reload_model_cost_mapr}
  2  s+      ""&6&B&BBGHYHcHcGde
 	

@
 (K 
 	U$77/4FG/,. 	  0BC  (%1%;%;%=" !. 0 0 ? ? K K!?@ !L !
 
 !:: / ; ; ? ?@P Q--44!?@ #A#-+/F$ ":+<dS$ 5 
 	
 	
" 3Es-.!!!QR^Q_`	

 <L>IYZ(%//1	
 	
;
	
8  
&&)J3q6('ST&GAx$P
 	

sO   8G?B0F4 +F0,A?F4 +F2,AF4 /G?0F4 2F4 4	G<=:G77G<<G?z/schedule/model_cost_map_reloadhoursc           
        K   |j                   t        j                  k7  rt        dd|j                          | dk  rt        dd      	 t        t        dd	      t        j
                  j                  j                  d
didt        | dd      ddt        | dd      id       d{    t        j                  d|  d       d|  dd| t        j                         j                         dS 7 H# t        $ r?}t        j                  dt!        |              t        ddt!        |             d}~ww xY ww)z
    ADMIN ONLY / MASTER KEY Only Endpoint

    Schedule periodic reload of the model cost map.
    This will create a background job that reloads the model cost map every specified hours.
    r
  rw
  r  r   rd  Hours must be greater than 0Nrx  rx
  r  r  Fr  r  r   r  r  z*Model cost map reload scheduled for every  hoursr  r`   r0  r  rz
  z*Failed to schedule model cost map reload: r  r<   r  r'  r]  r  r  r  r'   r}   rd  r   r  r  rp  r  r  r~
  r  r  s      rg   schedule_model_cost_map_reloadr
  2  s    " ""&6&B&BBGHYHcHcGde
 	

 z4RSS*
 (K 
 --44!?@ #A#-+0%H$ ":+0%H$ 5 
 	
 	
" 	!!8vF	

 DE7&Q#!*446	
 	
+	
6  
&&8QA	
 ?AxH
 	
	
>   A
EA#C; 0C91AC; 8E9C; ;	E:D>>EEc                   K   | j                   t        j                  k7  rt        dd| j                          	 t        t        dd      t        j
                  j                  j                  ddi	       d{    t        j                  d
       d
dt        j                         j                         dS 7 ?# t        $ r?}t        j                  dt        |              t        ddt        |             d}~ww xY ww)zp
    ADMIN ONLY / MASTER KEY Only Endpoint

    Cancel the scheduled periodic reload of the model cost map.
    r
  rw
  r  Nrx  rx
  r  r  r  z(Model cost map reload schedule cancelledr  r`   r0  rz
  z(Failed to cancel model cost map reload: r  r<   r  r'  r]  r  r  r
  r}   rd  r   r  r  rp  r  r  r  r  s     rg   cancel_model_cost_map_reloadr
  B3  s     ""&6&B&BBGHYHcHcGde
 	


 (K 
 --44!?@ 5 
 	
 	
 	!!"LM B!*446
 	
	
  
&&6s1vh?	
 &NsSTvh$W
 	
	
;   8D
AB? =B=>>B? <D
=B? ?	D:DDD
z&/schedule/model_cost_map_reload/statusc                   K   | j                   t        j                  k7  rt        dd| j                          	 t	        j
                  dt                t        t	        j
                  d       dddddS t        j                  j                  j                  d	d
i       d{   }||j                  t	        j
                  d       dddddS |j                  }|j                  d      }|t	        j
                  d       dddddS t        j                         }d}t        T	 t        j                  t              }||z
  }|j!                         dz  }||k  r|t#        |      z   j%                         }d|t        |dS 7 # t&        $ r"}	t	        j(                  d|	        Y d}	~	3d}	~	ww xY w# t&        $ r?}	t	        j*                  dt-        |	              t        ddt-        |	             d}	~	ww xY ww)zo
    ADMIN ONLY / MASTER KEY Only Endpoint

    Get the status of the scheduled model cost map reload job.
    r
  rw
  r  z4Checking model cost map reload status. Last reload: N/No database connection, returning not scheduledF	scheduledr  last_runnext_runr  r  r  z,No model cost map reload configuration foundr  /No interval configured, returning not scheduledr  r~
  r  Tz,Failed to get model cost map reload status: rx  )r  r<   r  r'  r}   rd  r  r]  r  r  r  r   r  r   r  r  r  r   r  rp  r|  r  r  
r  r  r~  r  r  r
  r  r  r  r  s
             rg    get_model_cost_map_reload_statusr
  s3  sM     ""&6&B&BBGHYHcHcGde
 	

H
 	!!BC]B^_	
   %%&WX""&  	  ,..==II!?@ J 
 
  M$=$=$E %%&TU""&  	  **$45! %%&WX""&  	   ( &1
U#+#9#9:T#U )58H)H&*@*N*N*PSW*W'*^;(9>+JJik  ,2 	
 	
U
N  U$,,/OPQs-STTU  
&&:3q6(C	
 A#a&J
 	
	
   8H=F= 8H9/F= (F)-F= H:F= HF= /AF 
F= HF= 	F:F50F= 5F::F= =	H:H  HHz/model/cost_map/sourcec                   K   | j                   t        j                  k7  rt        dd| j                          	 ddlm}  |       }t        j                  rt        t        j                        nd}i |d|iS # t        $ r?}t        j                  dt        |              t        ddt        |             d	}~ww xY ww)
a  
    ADMIN ONLY / MASTER KEY Only Endpoint

    Returns information about where the current model cost/pricing data was loaded from.

    Response fields:
    - source: "local" (bundled backup) or "remote" (fetched from URL)
    - url: the remote URL that was attempted (null when env-forced local)
    - is_env_forced: true if LITELLM_LOCAL_MODEL_COST_MAP=True forced local usage
    - fallback_reason: human-readable reason why remote failed (null on success)
    - model_count: number of models in the currently loaded cost map
    r
  rw
  r  r   )get_model_cost_map_source_infomodel_countz*Failed to get model cost map source info: rx  N)r  r<   r  r'  r  r
  rg  r  rn  rp  r}   r  r  )r  r
  source_infor
  r  s        rg   get_model_cost_map_sourcer
  3  s     * ""&6&B&BBGHYHcHcGde
 	


	
 56181C1Cc',,-

;
 	
  
&&8QA	
 ?AxH
 	
	
s(   8C?A; :C;	C:B>>CCz/reload/anthropic_beta_headersc           
        K   | j                   t        j                  k7  rt        dd| j                          	 t        t        dd      ddlm}  |       }t        j                         }|j                         a
t        j                  j                  j                  d	d
i       d{   }d}|r'|j                  r|j                  j                  d      }t        j                  j                  j!                  d	d
id
t#        ddd      ddt#        |dd      id       d{    t%        d |j'                         D              }t)        j*                  d|        d| dd||j                         dS 7 7 W# t,        $ r?}t)        j.                  dt1        |              t        ddt1        |             d}~ww xY ww)z
    ADMIN ONLY / MASTER KEY Only Endpoint

    Manually reload the Anthropic beta headers configuration from the remote source.
    This will fetch fresh configuration from the anthropic_beta_headers_config.json file.
    r
  rw
  r  Nrx  rx
  r   r  r  r  r  r  Tr  r  r   r  r  c              3   *   K   | ]  }|d vsd  yw))r  r  r  Nr^  r  s     rg   rO  z0reload_anthropic_beta_headers.<locals>.<genexpr>I4  s      
A5X,XA
s   	zOAnthropic beta headers config reloaded successfully in current pod. Providers: z<Anthropic beta headers configuration reloaded successfully! z providers updated.r  )r`   r0  providers_countrz
  z)Failed to reload anthropic beta headers: )r  r<   r  r'  r]  r  r  r   r  r  r  r  r  r  r   r  r  r'   rV  r  r}   rd  rp  r  r  )r  r  r  r  existing_beta_configexisting_beta_intervalr  r  s           rg   reload_anthropic_beta_headersr
  4  s      ""&6&B&BBGHYHcHcGde
 	

?
 (K 
 	V/1
  (-9-C-C-E* &3%5%5%D%D%P%P!GH &Q &
  
 "&$8$D$D%9%E%E%I%I &" --44!GH #I#-+/F$ ":+ASWX$ 5 
 	
 	
"  
!(
 
 	!!]^l]mn	

 VVdUeexy-%//1	
 	
C 
	
<  
&&7Ax@	
 &OPSTUPVx$X
 	
	
sO   8GA3F .F/A?F .F/AF GF F 	G:GGGz'/schedule/anthropic_beta_headers_reloadc           
        K   |j                   t        j                  k7  rt        dd|j                          | dk  rt        dd      	 t        t        dd	      t        j
                  j                  j                  d
didt        | dd      ddt        | dd      id       d{    t        j                  d|  d       d|  dd| t        j                         j                         dS 7 H# t        $ r?}t        j                  dt!        |              t        ddt!        |             d}~ww xY ww)z
    ADMIN ONLY / MASTER KEY Only Endpoint

    Schedule periodic reload of the Anthropic beta headers configuration.
    This will create a background job that reloads the configuration every specified hours.
    r
  rw
  r  r   rd  r
  Nrx  rx
  r  r  Fr  r  r   r  r  z2Anthropic beta headers reload scheduled for every r
  r  r
  z2Failed to schedule anthropic beta headers reload: r
  r
  s      rg   &schedule_anthropic_beta_headers_reloadr
  _4  s    " ""&6&B&BBGHYHcHcGde
 	

 z4RSS*
 (K 
 --44!GH #I#-+0%H$ ":+0%H$ 5 
 	
 	
" 	!!@vN	

 LE7RXY#!*446	
 	
+	
6  
&&@QI	
 GAxP
 	
	
r
  c                   K   | j                   t        j                  k7  rt        dd| j                          	 t        t        dd      t        j
                  j                  j                  ddi	       d{    t        j                  d
       d
dt        j                         j                         dS 7 ?# t        $ r?}t        j                  dt        |              t        ddt        |             d}~ww xY ww)z
    ADMIN ONLY / MASTER KEY Only Endpoint

    Cancel the scheduled periodic reload of the Anthropic beta headers configuration.
    r
  rw
  r  Nrx  rx
  r  r  r  z0Anthropic beta headers reload schedule cancelledr  r
  z0Failed to cancel anthropic beta headers reload: r
  r
  s     rg   $cancel_anthropic_beta_headers_reloadr
  4  s     ""&6&B&BBGHYHcHcGde
 	


 (K 
 --44!GH 5 
 	
 	
 	!!"TU J!*446
 	
	
  
&&>s1vhG	
 Ec!fXN
 	
	
r
  z./schedule/anthropic_beta_headers_reload/statusc                   K   | j                   t        j                  k7  rt        dd| j                          	 t	        j
                  dt                t        t	        j
                  d       dddddS t        j                  j                  j                  d	d
i       d{   }||j                  t	        j
                  d       dddddS |j                  }|j                  d      }|t	        j
                  d       dddddS t        j                         }d}t        T	 t        j                  t              }||z
  }|j!                         dz  }||k  r|t#        |      z   j%                         }d|t        |dS 7 # t&        $ r"}	t	        j(                  d|	        Y d}	~	3d}	~	ww xY w# t&        $ r?}	t	        j*                  dt-        |	              t        ddt-        |	             d}	~	ww xY ww)zw
    ADMIN ONLY / MASTER KEY Only Endpoint

    Get the status of the scheduled Anthropic beta headers reload job.
    r
  rw
  r  z<Checking anthropic beta headers reload status. Last reload: Nr
  Fr
  r  r  r  z4No anthropic beta headers reload configuration foundr  r
  r  r
  r  Tz4Failed to get anthropic beta headers reload status: rx  )r  r<   r  r'  r}   rd  r  r]  r  r  r  r   r  r   r  r  r  r   r  rp  r|  r  r  r
  s
             rg   (get_anthropic_beta_headers_reload_statusr
  4  sU     ""&6&B&BBGHYHcHcGde
 	

L
 	!!JKmJno	
   %%&WX""&  	  ,..==II!GH J 
 
  M$=$=$E %%F #"&  	  **$45! %%&WX""&  	   ( .9U#+#9#96$  *68H)H&*@*N*N*PSW*W'*^;(9>+JJik  ,: 	
 	
]
V  U$,,/OPQs-STTU  
&&B3q6(K	
 I#a&R
 	
	
r
  )rY  c                    K   yw)NzLiteLLM: RUNNINGr^  r~  s    rg   homer
  <5  s	     s   z/routesc                  &  K   ddl m}  g }t        j                  D ]o  }t	        |dd      }|#|j                  | j                  ||             5t        |d      sBt        |d      sO|j                  | j                  |             q d	|iS w)
zD
    Get a list of available routes in the FastAPI application.
    r   )	GetRoutesri  N)r  endpoint_router   rX   )r  r  )	%litellm.proxy.common_utils.get_routesr
  r   r  r  r  get_app_routesr  get_routes_for_mounted_app)r
  r  r  r
  s       rg   
get_routesr
  A5  s     
 @F M 
D9%MM((#1 )  UE"wuf'=MM)>>U>KLM fs   ABB*'Bz/{mcp_server_name}/mcp)GETrU   PUTDELETEPATCHOPTIONSHEAD)methodsmcp_server_namec           	        K   	 ddl m} ddlm} ddlm} |j                  |      }|j                  | |      }|t        dd|  d	
      t        |j                        }d|  |d<   ddlm} dddg fd}	 |||j                  |	       d{    ddlm}
 D ci c]$  \  }}|j!                         |j!                         & }}} |
||j#                  dd            S 7 Wc c}}w # t        $ r}|d}~wt$        $ rB}t'        j(                  d|  dt+        |              t        ddt+        |       
      d}~ww xY ww)z5Handle dynamic MCP server routes like /github_mcp/mcpr   r  )IPAddressUtils)MCPAuth)	client_ipNrx  zMCP server 'z' not foundr  z/mcp/rX   )handle_streamable_http_mcpFri   r{  c                    K   | d   dk(  rd| d   | j                  dg       y | d   dk(  r| j                  dd      z  y y w)	NrV   zhttp.response.startTr0  r%  zhttp.response.bodyr  ri   rK  )r`   response_bodyresponse_headersresponse_startedresponse_statuss    rg   custom_sendz&dynamic_mcp_route.<locals>.custom_send5  s\     v"77#' ")("3#*;;y"#= $88VS!99 9s   AA)receivesendr	  r	  zapplication/json)r$  r#  r%  r  z%Error handling dynamic MCP route for r\   rx  zInternal server error: )r  r  #litellm.proxy.auth.ip_address_utilsr
  litellm.types.mcpr
  get_mcp_client_ipget_mcp_server_by_namer'  r  r_  -litellm.proxy._experimental.mcp_server.serverr
  r
  starlette.responsesr+  r  r  rp  r}   r  r  )r
  r   r  r
  r
  r
  
mcp_serverr_  r
  r
  r+  r  r  headers_dictr  r
  r
  r
  r
  s                  @@@@rg   dynamic_mcp_router
  5  s    @X	
 	G-"44W=	.EEy F 

 ,6G{(S  W]]#01f	

 !	: )7??
 	
 	

 	1;KL41a
AHHJ.LL!' #''8JK	
 	
	
 M   X""3O3DBs1vhO	
 6McRSfX4VWW	XsY   EBC< C4C< ,)C6C< 3E4C< 6C< <	EDE=EEE)rX   r   )NNrA  rP  )NNNNFFNNr  NFTTNFFN)FN)r  (N  r  rl  enumr  r  r  r  rq   r	  rN  r"  r,  rg  r  r  warningsr   r   r   typingr   r   r   r	   r
   r   r   r   r   r   r   r   r   r   r  r  websockets.exceptionspydanticr   r   litellm._uuidr   r  r   r   r   r   r   r   r   r   r   r    r!   r"   r#   r$   r%   *litellm.litellm_core_utils.litellm_loggingr&   *litellm.litellm_core_utils.safe_json_dumpsr'   litellm.proxy._typesr(   r)   r*   r+   r,   r-   r.   r/   r0   r1   r2   r3   r4   r5   r6   r7   r8   r9   r:   r;   r<   r=   r>   r?   r@   rA   rB   rC   rD   rE   rF   )litellm.proxy.common_utils.callback_utilsrG   rH   )litellm.proxy.common_utils.realtime_utilsrJ   rO  rK   rL   rM   rN   rm  rO   rP   rz  rQ   opentelemetry.tracerR   _Span"litellm.integrations.opentelemetryrS   rY   r  rC  rh   filterwarningsUserWarningrk   r  rX   insertr  r[  backofffastapir  r  apscheduler.schedulers.asynciorl   rS  r  rs   rw   collectionsrx   
contextlibry   	functoolsrz   rg  r{   r\  r}   r~   rI  r   r   #litellm.caching.redis_cluster_cacher   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   litellm.exceptionsr   %litellm.integrations.custom_guardrailr   "litellm.integrations.custom_loggerr   1litellm.integrations.SlackAlerting.slack_alertingr   'litellm.litellm_core_utils.core_helpersr   r   .litellm.litellm_core_utils.credential_accessorr   r   LiteLLMLoggingObj0litellm.litellm_core_utils.sensitive_data_maskerr   r	  r   r   &litellm.llms.vertex_ai.vertex_llm_baser   ;litellm.proxy._experimental.mcp_server.byok_oauth_endpointsr   mcp_byok_oauth_router=litellm.proxy._experimental.mcp_server.discoverable_endpoints!mcp_discoverable_endpoints_router5litellm.proxy._experimental.mcp_server.rest_endpointsmcp_rest_endpoints_routerr
  r   mcp_app4litellm.proxy._experimental.mcp_server.tool_registryr   +litellm.proxy.agent_endpoints.a2a_endpoints
a2a_routerr  r   'litellm.proxy.agent_endpoints.endpointsagent_endpoints_router0litellm.proxy.agent_endpoints.model_list_helpersr   r   5litellm.proxy.analytics_endpoints.analytics_endpointsanalytics_router7litellm.proxy.anthropic_endpoints.claude_code_endpointsr   +litellm.proxy.anthropic_endpoints.endpointsanthropic_router2litellm.proxy.anthropic_endpoints.skills_endpointsanthropic_skills_routerlitellm.proxy.auth.auth_checksr   r   r   litellm.proxy.auth.auth_utilsr   litellm.proxy.auth.handle_jwtr   "litellm.proxy.auth.litellm_licenser   rq  r   r   r   r   r   $litellm.proxy.auth.user_api_key_authr   r   r   )litellm.proxy.batches_endpoints.endpointsbatches_routerlitellm.proxy.caching_routescaching_router'litellm.proxy.common_request_processingr   r   r   r   &litellm.proxy.common_utils.debug_utilsr   debugging_endpoints_router0litellm.proxy.common_utils.encrypt_decrypt_utilsr   r   .litellm.proxy.common_utils.html_forms.ui_loginr   -litellm.proxy.common_utils.http_parsing_utilsr   r   r   r   ,litellm.proxy.common_utils.load_config_utilsr   r   0litellm.proxy.common_utils.openai_endpoint_utilsr   &litellm.proxy.common_utils.proxy_stater   +litellm.proxy.common_utils.reset_budget_jobr   (litellm.proxy.common_utils.swagger_utilsr   +litellm.proxy.container_endpoints.endpointscontainer_router,litellm.proxy.credential_endpoints.endpointscredential_routerr?  r   "litellm.proxy.db.exception_handlerr   !litellm.proxy.discovery_endpointsr   -litellm.proxy.fine_tuning_endpoints.endpointsfine_tuning_routerr   (litellm.proxy.google_endpoints.endpointsgoogle_router,litellm.proxy.guardrails.guardrail_endpointsguardrails_router(litellm.proxy.guardrails.init_guardrailsr   r   rR  r   rA  health_router,litellm.proxy.hooks.model_max_budget_limiterr   .litellm.proxy.hooks.prompt_injection_detectionr   -litellm.proxy.hooks.proxy_track_cost_callbackr   'litellm.proxy.image_endpoints.endpointsimage_router$litellm.proxy.litellm_pre_call_utilsr   9litellm.proxy.management_endpoints.access_group_endpointsaccess_group_router>litellm.proxy.management_endpoints.budget_management_endpointsbudget_management_routerr  cache_settings_router@litellm.proxy.management_endpoints.callback_management_endpoints$callback_management_endpoints_routerrn  r   r   7litellm.proxy.management_endpoints.compliance_endpointscompliance_routerr  config_override_router9litellm.proxy.management_endpoints.cost_tracking_settingscost_tracking_settings_router5litellm.proxy.management_endpoints.customer_endpointscustomer_router@litellm.proxy.management_endpoints.fallback_management_endpointsfallback_management_router:litellm.proxy.management_endpoints.internal_user_endpointsinternal_user_routerr   <litellm.proxy.management_endpoints.jwt_key_mapping_endpointsjwt_key_mapping_router;litellm.proxy.management_endpoints.key_management_endpointsr   r   r   key_management_router;litellm.proxy.management_endpoints.mcp_management_endpointsmcp_management_routerJlitellm.proxy.management_endpoints.model_access_group_management_endpoints$model_access_group_management_router=litellm.proxy.management_endpoints.model_management_endpointsr   r   r   model_management_router9litellm.proxy.management_endpoints.organization_endpointsorganization_router3litellm.proxy.management_endpoints.policy_endpointspolicy_router4litellm.proxy.management_endpoints.project_endpointsproject_router<litellm.proxy.management_endpoints.router_settings_endpointsrouter_settings_router/litellm.proxy.management_endpoints.scim.scim_v2r   ;litellm.proxy.management_endpoints.tag_management_endpointstag_management_router:litellm.proxy.management_endpoints.team_callback_endpointsteam_callback_router1litellm.proxy.management_endpoints.team_endpointsteam_routerr   r   <litellm.proxy.management_endpoints.tool_management_endpointstool_management_router)litellm.proxy.management_endpoints.ui_ssor   ui_sso_router2litellm.proxy.management_endpoints.usage_endpointsusage_ai_routerAlitellm.proxy.management_endpoints.user_agent_analytics_endpointsuser_agent_analytics_router+litellm.proxy.management_helpers.audit_logsr   6litellm.proxy.middleware.in_flight_requests_middlewarer   3litellm.proxy.middleware.prometheus_auth_middlewarer   %litellm.proxy.ocr_endpoints.endpoints
ocr_router.litellm.proxy.openai_evals_endpoints.endpointsevals_router4litellm.proxy.openai_files_endpoints.files_endpointsopenai_files_routerr   >litellm.proxy.pass_through_endpoints.llm_passthrough_endpointsr   llm_passthrough_routerr   r-  r   pass_through_router,litellm.proxy.policy_engine.policy_endpointspolicy_crud_router4litellm.proxy.policy_engine.policy_resolve_endpointspolicy_resolve_routerr  prompts_routerlitellm.proxy.public_endpointspublic_endpoints_router%litellm.proxy.rag_endpoints.endpoints
rag_router*litellm.proxy.realtime_endpoints.endpointswebrtc_router(litellm.proxy.rerank_endpoints.endpointsrerank_router.litellm.proxy.response_api_endpoints.endpointsresponse_routerlitellm.proxy.route_llm_requestr   (litellm.proxy.search_endpoints.endpointssearch_router5litellm.proxy.search_endpoints.search_tool_managementsearch_tool_management_routerr  cloudzero_router7litellm.proxy.spend_tracking.spend_management_endpointsspend_management_router1litellm.proxy.spend_tracking.spend_tracking_utilsr   r  vantage_routerlitellm.proxy.types_utils.utilsr   r  ui_crud_endpoints_routerr  r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   .litellm.proxy.vector_store_endpoints.endpointsvector_store_router9litellm.proxy.vector_store_endpoints.management_endpointsvector_store_management_router4litellm.proxy.vector_store_files_endpoints.endpointsvector_store_files_router4litellm.proxy.vertex_ai_endpoints.langfuse_endpointslangfuse_router'litellm.proxy.video_endpoints.endpointsvideo_routerlitellm.routerr   r   r   r   litellm.schedulerr  r  *litellm.secret_managers.aws_secret_managerr  "litellm.secret_managers.google_kmsr  r  r  r  r  r  )litellm.types.integrations.slack_alertingr	  litellm.types.llms.anthropicr
  r  r  r  litellm.types.llms.openair  +litellm.types.proxy.control_plane_endpointsr  Clitellm.types.proxy.management_endpoints.model_management_endpointsr  /litellm.types.proxy.management_endpoints.ui_ssor  r  litellm.types.realtimer  rP  r  r  r  r  r  r  litellm.types.schedulerr  "litellm.types.secret_managers.mainr  r  r  r  ModelMapInfor  r  r   litellm._versionr!  rp  suppress_debug_infor  r"  r#  r$  r%  r&  r'  r(  r)  r*  r+  r,  r-  r.  r/  r0  fastapi.encodersr1  fastapi.middleware.corsr2  fastapi.openapi.docsr4  fastapi.openapi.utilsr5  r	  r6  r7  r8  r9  r:  fastapi.routingr;  fastapi.securityr<  fastapi.security.api_keyr=  fastapi.staticfilesr>  litellm.types.agentsr?  enterprise_routerlitellm.proxy.enterpriseproxy
enterprise*litellm_enterprise.proxy.enterprise_routes_enterprise_router%litellm_enterprise.proxy.proxy_serverr@  rA  r  r  r  rB  rR  airgapped_license_datarC  r  rE  proxy_stater  rG  r(  rI  rJ  r  r	  fallback_login_linkmodel_hub_link
ui_message	chat_linkcustom_swagger_message_title_descriptionr_  rq  r  r  #vertex_live_passthrough_vertex_baser  r  r  openapiEnumr  exception_handlerr+  originsr  r	  r|  r:  packaged_ui_pathr5  litellm_asset_prefixr4  r<  rF  r  rP  r  r	  default_runtime_ui_pathruntime_ui_pathr  should_use_runtime_pathis_pre_restructuredhas_contentrd  r|  r  r	  r	  is_writablera  rootdirsrg  rb   rj  rd  r   r	  r  r$  r	  modified_contentr_   UnicodeDecodeErrorrA  rB  r}  rl  r  add_middlewarer  r  r  r  r  r_  rY  rZ  r  ra  r`  rc  user_configr^  rR  local_loggingrb  r  r  r  r  r  log_filer  rQ  r  rS  r]  r  r  r  r  r  model_max_budget_limiterr  r  r  r  r  r  rT  rV  r  r  rW  rX  rY  rZ  rh  r[  r\  rf  r  re  rj  r  r  r  r  r  r  r1  r  r[  r2  ri  r  r  r  r  async_resultcelery_app_conn	celery_fnr=  r  r  rk  r  r  r  r  r  r  r  r  r  r%  r.  r3  r:  rE  rY  r  rz  r|  r  rG  r  ro  r  r  r  r  r  r  r  r  r  r4  r^  postr  r  r  r  bytesr  r  r  r  r   r  r  r   r#  r
  r'  r+  r0  r4  r7  r;   litellm.llms.base_llm.base_utilsr<  rL  rP  rd  rk  rp  ru  ry  r  r  r  r  r  r  r  r  r  r  r  r  r	  r	  r!	  r(	  r,	  r7	  rA	  r?	  rI	  rk	  r~	  r	  r	  r	  r	  r	  r	  r	  r	  r	  r
  r

  r
  r
  r
  r%
  r)
  r+
  r>
  r@
  rH
  r  ru
  r}
  r
  r
  r
  r
  r
  r
  r
  r
  r
  r
  include_router	api_router
  r^  ri   rg   <module>r     s;        	 	     
     2 2   "    $     " B                 B M 
 %1@DDM 3 c3h # #    	K 8
 $  rwww	U?	 8 $ *    H 9 A    " 4 I ; K N S P P = I # L N T S 
 F 4 ;  
 O B 
 T G W O     > = F F D D R T S S G G K K V P P L T  < ; T   I H J L L    
  
 X H G T   N X T S  Y X F Q     V L L F N L T 9 9 L X R Q S ; ;         ( Y K   2 1 C C > >   H G   A @ K K   7 6  > =  
 6 5  K J 9 K K G(( #          " . - 2 2 4 4 - -    & % 1 1 1 1 + + , , K 11#WKK*?T?VX&;<V
 () #..0d 0 )) 8 * :C1: '#  l+- *2/0'0*-.U*V'?Hryy7@ -x}  187;-u;0551- c
")*/: $%%897y  AJ  K^  J_  _`  a
 
T T
 
3N3C  D_  `  `
 )	 
1)  =K  L  L
 N  4@<	/] 	 BII
VWmVnnrs}r~
 AAW@XX\]g\h	i &&>> `!7 `! `!F _
  '1l #
 . -FR4 299_g&&0\ CK %CKTYY  ~&
G 
. 
 '
 
%y	''//"''//(";<Kww||K%HG2s t   2- - -^!!'*!	tSy	!4 ")).399;vEK "7"2bii 13JKO ""23"""./ 0- .	
 .1AA5oF&7 .% %%(EoEV&WX%G !4( (() *8 9 &G & %%"?"33]^ 8 /NGU ) -$,,//@5' J66F5G HLM + 	"!!$ABRAS"TU" "'*"""y(]^	

 ,3bii1( ((Fwi PG H &-RWWW%5 &!!dE % %!H "T8 <I((
 !!!)S7C /q&'ffhG/ ,3??34/0,( ,<+C+CD/00NO,(
 ")S7C 6qGG$456C%!&!R IIbggll7G<=  
 II
 'bggll7G<=   IIe[7>TIJC D <
5g>bii1% %%-gY6RS ( ((+G9 5X Y 'w/% %%(CG9&MN ggoobggooh78   %%+     + ,   - .<*  ?#,299-@#A 8C= As?(4WWSEW*7 +7 

  '+ x} +#
HV #!% % $ ?C htDcN';< C 
HSM  -1x[)* 1(,x% , 	  	 0DDJJ   0DDJJ  B!       5 56N O 	 8 	 EJ 5cD!@A I     3    (-  ,%* d *%) "#  	   DF d3c4S#X+?&? @@A F&+ #$% !t 2 3 7<gn-t34 <$E !$E !; +   lOS )K L S 4 15 x. 5 )  	 	!  &* " 04 (+, 3w 84 "
4 
>
# #e # #L1
C=1
c]1
 c]1
 E?	1
h### #Z !%C=c] # c]	
 E? tn 49
D

Xe_   

d^
 c]
 "	
2  	
 D


 

>l3^	Y 	S/ S/l^ }3 

	#{~36,!/6,?C6,rGD GS G5(5( "%5( 	5(
  5( 395(pd!/d?CdN!/?C *, $ Y
&v vt (9 :;CUBV   W%678@R?S   )00A(B-2!27/4',#'B%B$TNB c]B "*$	B
 'tnB tnB C=B C=BBJ +,-
	  
 +,-
	   )00A(B<<%<<~ +,-
	  
 +,-
	  
 ,+,-
	  
 7+,-
	]$9:NoN	    (/0A(B	_
_
_
 C=_
 &	_
*_
D W->%?$@   '*;"<!=]O   '+,-
  
 2+,-
    (/0A(B	u
u
u
 C=u
 &	u
 u
p +,-!
	   +,-!
	   &+,-!
	   1+,-!
	    (/0A(B	v
v
v
 C=v
 &	v
0v
r +,-!
	   +,-!
	   )00A(Bjjj &jjZ	)	E4K 	 +,-
  
 +,-
   )00A(Bjjj &jjZ +,-
  
 +,-
   Cy(/0A(B	UUU U &	UU~  ! )7==] %2GMMY% &3W]]Q& 9:C= SM c] "J ,-

 

5c?C 
 .
 ~{  '--C !.W! 9:oIoIoI oI oI  oIt +,-
  
 +,-
   )00A(BUUU &UUp +,-
  
 +,-
   )00A(BUUU &UUp (+,-
  
 %+,-
   )00A(B	TTT T &	TTn +,-
  
 +,-
   )00A(BTTT &TTn +,-
  
 +,-
   )00A(B	RRR R &	RRj &+,-
  
 #+,-
   )00A(B	VVV V &	VVr &+,-
  
 #+,-
   )00A(B	RRR R &	RRj "+,-
  
 +,-
   )00A(B	aaa a &	aaX > =66$'6
8$%x}hsmCD6r 
+,-%	  F!2 F4 FFR $
+,-  

 


2 
+,-&	  W%9 WWJ% L) 
$Z	>$%1B	$Z(*T
** &* L)	*Z* 12** 
#s3x-*Z) d3i-.) )  )  
#tCy.	) X %   
#Y &A%AA A T
	A
 
$ZAJ PTBS>B"&B<DV<LB	#s(^BX "I/T#s(^$I/I/ I/ 	I/
 C=I/ I/ c]I/ 4S#X#./I/X' '0B 'Z MT#s(^$Mc]M M 
$sCx.	M`%T#s(^$%
% % #	%
 SM% 
#s(^%PvT#s(^$vv  v 	v
 
$sCx.vr,*,*SM,* 4#,*^  ^
	+,-   )00A(B(7=== (5w}}B( +8'--K+ "a]q9bka8)GMMO +W]]H *GMMw *GMMb  -w}}4 9`%`C=`
 tn` "$` D>` ` ` SM`" c]#`( SM)`0 SM1`8 }9``F C
	+,-   )00A(B+/$("&	z
%z
#C=z
 !z
 h	z
z
z P
	+,-   )00A(B+6$("&!"i
%i
#C=i
 !i
 h	i

 c]i
 smi
i
X #A
	+,-   )00A(B+6$("&!"P%P#C=P !P h	P
 c]P smPPf I
	+,-   )00A(B+/$("&!"NH%NH#C=NH !NH h	NH
 c]NH smNHNHb( ($ (V 
	+,-  
 
	+,-   )00A(B&*C %C smC C L(,S	@H	
D 
	+,-   )00A(B!%z"%z"#z"
z"z _
	+,-  4 X
+,-   )00A(Bc%ccN 
	+,-	    (/0A(B	q
q
q
 C=q
 &	q
q
h 	.!1UK
' 
 L
@   , ,,^ 5  BG BBJ 5  UG UUp E  >
W >
>
B 	 E:o# o o ;od 
#u=No N >Nb E2# 3# /S@ 0S@l 515I 25Iv 
	+,-"   >EEV=WG+
G+,:G+G+T 
	+,-"   =DDU<V**+9**Z 
	+,-"   )00A(B3
3%33l 
	+,-"   )00A(BF
F%FFT 
+,-	   V]]nUo K
Z K
N K
K
^ 
+,-	   )00A(BE
E%EEP 
+,-"   )00A(B44%44n 
+,-	   )00A(BL+,L%L 
*LL^ 
+,-	   )00A(B?
?%??D 
+,-	   )00A(BT

T
%T
T
n 
+,-	  c
c
L 
+,-	  J ( 
	+,-	   )00A(BP
%P
P
f %
	+,-	   )00A(B>
>
%>
>
B %
	+,-	   )00A(B(
%(
(
V ,
	+,-	   )00A(BW
%W
W
t 
	+,-	   )00A(B(
%(
(
\ $
	+,-	   )00A(BO
%O
O
d -
	+,-	   )00A(B>
>
%>
>
B -
	+,-	   )00A(B)
%)
)
X 4
	+,-	   )00A(B[
%[
[
| Cw'89:;  < IW->%?$@A B`   6    ? #   > "   * +   = !   :    :    <     # $   = !   <     % &   & '   1 2   , -   $ %   ) *   = !   ( )   ( )   # $   * +   <     1 2   = !   ? #   & '   = !   ( )   ' (   ;    = !   ;    & '   > "   ? #   * +   # $   > "   > "   # $   $ %   = !   ? #   % &   ( )   0 1   > "   7 8   - .   + ,   & '   ' (   ) *   + ,   * +   7 8   ( )   ) *   0 1   ) *   - .   ( )   ) *   . /   $ %   0 1   ) *   $ %   :    & ' H  BXS BX7 BX	BXJ 		~7	 +   , -   4 5ak  U
+A3.RS
TTUL  G\   	  #"#v/ /6 6.I ! !D  
&&&@	A3O	
 	
  
&&&5gYbD	
 	


  		s`  %By7 <	Bz Bz  'B{ !JB} 4B{*B{AB{*B{3B{*;B"B} BB{< y7Bzy<BzzBzz	BzzBzz Bz>z'Bz.z-Bz>z.Bz7z4Bz>z6Bz7z7Bz>z=Bz>{B{{B{{B{{B{*{B{'{"B{*{*B{9{5B} {8B{9{9B} {<B}|B|"|B} |"	B}|+B}}B} }B}}B} }B}}B}