Ë
    uPêjÈK ã                   ó¦  — 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m	Z	m
Z
 d dlmZmZ d dlmZmZmZmZmZ d dlZd dlmZmZmZmZmZmZ d dlm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% d d
l&m'Z' d dl(m)Z) d dl*m+Z+m,Z,m-Z-m.Z.m/Z/m0Z0m1Z1m2Z2m3Z3m4Z4 d dl5m6Z6 d dl7m8Z8 d dl9m:Z: d dl;m<Z< d dl=m>Z>m?Z?m@Z@mAZAmBZBmCZC d dlDmEZE d dlFmGZG d dlHmIZImJZJ d dlKmLZL deMddfd„ZN eOg eI¢eJ¢d‘­«      ZPeeOeQ      eRd<   	 d™de
eQeSf   de
eQeSf   deTdeMeQeSf   fd„ZUd„ ZV e«       ZWeeRd <   ed!   eQz  ZX G d"„ d#e«      ZY G d$„ d%e«      ZZeWj·                  d&d'g ee8«      g¬(«      d)efd*„«       Z\eWj·                  d+d'g ee8«      g¬(«       ee8«       ejº                  d,¬-«      fd.e3d/eXfd0„«       Z^deMfd1„Z_d2„ Z`	 dšd3eQd4ead5ead6ebd7eQdz  d8eQdz  fd9„Zcd:eadeMfd;„Zdd<eMd4ead5eadeMfd=„Ze	 dšd>eMd?eMd6ebd@eQdz  fdA„Zf	 dšd:ead4ead5ead6ebd@eQdz  f
dB„Zg eOe/jÐ                  jÒ                  e/jÔ                  jÒ                  h«      ZkeeRdC<   d.e3deTfdD„ZldEeMdeMfdF„Zmd:eadGeQdz  d8eQdz  dendz  fdH„ZodIeMdJendeMfdK„Zp	 	 d›dL„ZqdGeQdz  d8eQdz  deQdz  fdM„ZreWj·                  dNd'g ee8«      g¬(«       ee8«       ejº                  ddO¬-«       ejº                  ddP¬-«      fdQed.e3dGeQdz  d8eQdz  fdR„«       ZseWj·                  dSd'g ee8«      g¬(«       ee8«       ejº                  ddT¬-«       ejº                  ddU¬-«       ejº                  dVdWdXdY¬Z«       ejº                  d d[d ¬\«      fd.e3dGeQdz  d]eQdz  d^etd_etf
d`„«       ZueWj·                  dad'g ee8«      g¬(«       ee8«      fd.e3fdb„«       ZveWj·                  dcd'g ee8«      g¬(«       ee8«      fd.e3fdd„«       ZwdeMeQef   dz  fde„ZxdfeMeQef   deafdg„ZyeWj·                  dhd'g ee8«      g¬(«       ee8«      fd.e3fdi„«       Zz G dj„ dke«      Z{dl ejø                  «       dmœa}e{eRdn<   doZ~eeRdp<   dqZeeRdr<   de{fds„Z€de{fdt„Z�eWj·                  dud'g ee8«      g¬(«      eWj·                  dvd'g ee8«      g¬(«      dw„ «       «       Z‚dx„ ZƒdyZ„eeRdz<   deTfd{„Z…	 dšdQedz  deMeQef   fd|„Z†deTfd}„Z‡deTfd~„ZˆdeQdz  fd„Z‰d)eddfd€„ZŠdQedeQfd�„Z‹eWj·                  d‚d'g¬ƒ«      dQefd„„«       ZŒeWj·                  d…d'g ee8«      g¬(«      dQefd†„«       Z�eWj·                  d‡d'g ee8«      g¬(«      dˆ„ «       ZŽeWj·                  d‰d'g¬ƒ«      d)efdŠ„«       Z�eWj·                  d‹d'g¬ƒ«      eWj·                  dŒd'g¬ƒ«      dQefd�„«       «       Z�eW�j#                  d‚d'g¬ƒ«      dŽ„ «       Z’eW�j#                  d‹d'g¬ƒ«      eW�j#                  dŒd'g¬ƒ«      d�„ «       «       Z“eW�j)                  d�d'g ee8«      g¬(«       e�j*                  dd‘¬-«       e�j*                  dd’¬-«       e�j*                  dd“¬-«       ee8«      fd)ed”ed•   dz  d–eMd—eMd.e3f
d˜„«       Z–y)œé    N)ÚIterableÚMapping)ÚdatetimeÚ	timedelta)ÚAnyÚFinalÚLiteralÚ	TypedDictÚcast)Ú	APIRouterÚDependsÚHTTPExceptionÚRequestÚResponseÚstatus)ÚReadOnly)Úverbose_loggerÚverbose_proxy_logger)ÚHEALTH_CHECK_TIMEOUT_SECONDS)ÚMS_TEAMS_ALERT_HEADERSÚbuild_ms_teams_payloadÚget_ms_teams_webhook_url)ÚCustomLoggerRegistry)ÚAsyncHTTPHandler)
Ú	AlertTypeÚCallInfoÚEnterpriseLicenseDataÚLitellm_EntityTypeÚLitellmUserRolesÚProxyErrorTypesÚProxyExceptionÚSpecialModelNamesÚUserAPIKeyAuthÚWebhookEvent)Ú_BANNED_REQUEST_BODY_PARAMS)Úuser_api_key_auth)ÚPrismaDBExceptionHandler)Úcount_live_proxy_workers)Ú ADMIN_ONLY_HEALTH_DISPLAY_PARAMSÚ_clean_endpoint_dataÚ'_update_litellm_params_for_health_checkÚ0health_check_filter_kwargs_from_general_settingsÚperform_health_checkÚrun_with_timeout©Úget_in_flight_requests)ÚGracefulShutdownManager)Ú._ADMIN_CONFIG_FIELDS_TO_CLEAR_ON_BASE_OVERRIDEÚclientside_credential_keys)Úget_secret_boolÚparamsÚreturnc                 óè  — t        | t        «      sy| g}t        | «      h}|rÐ|j                  «       }t        |t        «      r|j	                  «       }nt        |t
        «      r|}nŒG|D ]‚  }t        |t        «      r |j                  d«      rt        dddi¬«      ‚t        |t        t
        f«      sŒJt        |«      |vsŒX|j                  t        |«      «       |j                  |«       Œ„ |rŒÏyy)a/  
    Validate that the provided params do not contain any ``os.environ/``
    references. Values with that prefix are expected to come only from
    server-side configuration (already resolved before reaching here). If a
    request-supplied value still carries the prefix, raise ``HTTPException``.
    Nzos.environ/é�  ÚerrorzHEnvironment variable references are not permitted in request parameters.©Ústatus_codeÚdetail)Ú
isinstanceÚdictÚidÚpopÚvaluesÚlistÚstrÚ
startswithr   ÚaddÚappend)r5   ÚstackÚseenÚsrcrA   Úvalues         úu/home/oem/CyberBrain26-unified/.venv/lib/python3.12/site-packages/litellm/proxy/health_endpoints/_health_endpoints.pyÚ_reject_os_environ_referencesrL   B   sÓ   € ô �fœdÔ#Øà"( €EÜ ›Z˜L€Dá
Ø�i‰i‹kˆÜ�cœ4Ô Ø'*§z¡z£|‰FÜ˜œTÔ"Ø‰Fààò 	$ˆEÜ˜%¤Ô%¨%×*:Ñ*:¸=Ô*IÜ#Ø #Ø#Ð%oÐpôð ô ˜%¤$¬ Õ.´2°e³9ÀDÒ3HØ—‘œ˜E›Ô#Ø—‘˜UÕ#ð	$ô ó    Úlitellm_credential_nameÚ_CONFIG_CONNECTION_FIELDSÚconfig_paramsÚrequest_paramsÚallow_client_side_credentialsc                 óÊ   ‡— |rt        | «      S t        ˆfd„t        D «       «      st        | «      S | j                  «       D ��ci c]  \  }}|t        vsŒ||“Œ c}}S c c}}w )aå  Return the configured parameters to merge under a connection-test request.

    A request that sets its own connection fields describes a connection of its
    own, so the configuration's credentials are not carried into it: they belong
    to the endpoint the configuration names. Anything the request does not set
    still comes from the configuration, which is what lets a request name a
    configured model and test it as configured.

    ``litellm_credential_name`` is dropped alongside the literal credential
    fields: it names a stored credential that ``load_credentials_from_list``
    resolves into the same secrets further down the call, so leaving it in place
    would reintroduce them by reference.

    ``general_settings.allow_client_side_credentials`` is the existing proxy-wide
    opt-in for callers supplying their own connection parameters. Where an admin
    has enabled it, a request may pair its own endpoint with the configured
    credentials, as it could before.
    c              3   ó&   •K  — | ]  }|‰v –— Œ
 y ­w©N© )Ú.0ÚparamrQ   s     €rK   ú	<genexpr>z0_config_base_for_health_check.<locals>.<genexpr>…   s   øè ø€ ÒP¨5ˆu˜Ô&ÑPùs   ƒ)r>   Úanyr%   ÚitemsrO   )rP   rQ   rR   ÚkeyrJ   s    `   rK   Ú_config_base_for_health_checkr]   l   sZ   ø€ ñ. %Ü�MÓ"Ð"ÜÓPÔ4OÔPÔPÜ�MÓ"Ð"Ø)6×)<Ñ)<Ó)>×g™:˜3 À#ÔMfÒBfˆC�‰JÓgÐgùÓgs   ÁAÁAc                 ó4  — t        | t        «      r| S t        | d«      r| j                  r| j                  S t        | d«      rLt	        j
                  | j                  «      }t        | d«      r| j                  |v r| j                  S |r|d   S t        | «      S )aÜ  
    Get the callback identifier string, handling both strings and objects.

    This function extracts a string identifier from a callback, which can be:
    - A string (returned as-is)
    - An object with a callback_name attribute
    - An object registered in CustomLoggerRegistry
    - Falls back to callback_name() helper function

    Args:
        callback: The callback to identify (can be str or object)

    Returns:
        str: The callback identifier string
    Úcallback_nameÚ	__class__r   )r=   rC   Úhasattrr_   r   Ú%get_all_callback_strs_from_class_typer`   )ÚcallbackÚcallback_strss     rK   Úget_callback_identifierre   Š   sŽ   € ô  �(œCÔ ØˆÜˆx˜Ô)¨h×.DÒ.DØ×%Ñ%Ð%Üˆx˜Ô%Ü3×YÑYÐZb×ZlÑZlÓmˆÜ�8˜_Ô-°(×2HÑ2HÈMÑ2YØ×)Ñ)Ð)ÙØ  Ñ#Ð#Ü˜Ó"Ð"rM   Úrouter)Úslack_budget_alertsÚlangfuseÚlangfuse_otelÚslackÚms_teamsÚ	openmeterÚwebhookÚemailÚ
braintrustÚdatadogÚdatadog_llm_observabilityÚgeneric_apiÚarizeÚgalileoÚnewrelicÚsqsc                   ó   — e Zd ZU ee   ed<   y)Ú_ServiceTestErrorDetailr9   N©Ú__name__Ú
__module__Ú__qualname__r   rC   Ú__annotations__rV   rM   rK   rx   rx   ¿   s   … Ø�C‰=ÔrM   rx   c                   ó.   — e Zd ZU ee   ed<   ee   ed<   y)Ú_ServiceTestSuccessResponser   ÚmessageNry   rV   rM   rK   r   r   Ã   s   … Ø�S‰MÓØ�c‰]ÔrM   r   z/testÚhealth)ÚtagsÚdependenciesÚrequestc              ƒ   ó*   K  — ddl m} d || «      iS ­w)a  
    [DEPRECATED] use `/health/liveliness` instead.

    A test endpoint that pings the proxy server to check if it's healthy.

    Parameters:
        request (Request): The incoming request.

    Returns:
        dict: A dictionary containing the route of the request URL.
    r   )Úget_request_routeÚroute)Úlitellm.proxy.auth.auth_utilsr†   )r„   r†   s     rK   Útest_endpointr‰   È   s   è ø€ õ& @àÑ& wÓ/Ð0Ð0ùs   ‚z/health/serviceszSpecify the service being hit.)ÚdescriptionÚuser_api_key_dictÚservicec              ƒ   óL  K  — 	 ddl m}m}m} |€t	        dddi¬«      ‚|dvrt	        ddd	|› d
t
        › �i¬«      ‚d}|t        j                  v rd}n=t        j                  D ]*  }t        |dd«      |k(  rd} nt        |«      }||k(  sŒ(d} n |dk(  s|dk(  s|dk(  s|r3|dk7  r.t        j                  ddddœgdd¬«      ƒ d{  –—† }dd|› d�dœS |dk(  r<ddlm}	  |	«       }
|
j                  «       ƒ d{  –—† }|d   |d   d k(  r|d!   dœS d"dœS |d#k(  r\dd$lm} dd%lm}  |d#«      }|€	 |d¬&«      }t%        ||«      sJ ‚|j                  «       ƒ d{  –—† }|d   |d   d k(  r|d!   dœS d'dœS |d(k(  r<dd)lm}  |«       }|j                  «       ƒ d{  –—† }|d   |d   d k(  r|d!   dœS d*dœS |d+k(  r<dd,lm}  |«       }|j                  «       ƒ d{  –—† }|d   |d   d k(  r|d!   dœS d-dœS |dk(  rIdd.lm}  |«       }|j2                  j5                  «        t        j6                  ddddœgdd¬«      }dd/dœS |d0k(  rdt9        | «      st	        t:        j<                  dd1i¬«      ‚dd2lm }  |«       }|j                  «       ƒ d{  –—† }|d   |d   d k(  r|d!   dœS d3dœS |d4k(  rhtC        | jD                  xs d5d6d| jF                  | jH                  | jJ                  tL        jN                  ¬7«      }|jQ                  d8|¬9«      ƒ d{  –—†  n5|d:k(  r0dd;l)m*}  |«       }|j                  «       ƒ d{  –—† }|d   |d!   dœS |d<k(  s|d=k(  �rõd<|jW                  d>g «      v �rÍ|jX                  jZ                  ��|jX                  jZ                  D ]ë  }|jX                  j\                  �||jX                  j\                  vrŒ2d?}|t^        j`                  k(  rd@}n†|t^        jb                  k(  rdA}np|t^        jd                  k(  rdB}nZ|t^        jP                  k(  rdC}nD|t^        jf                  k(  rdD}n.|t^        jh                  k(  rdE}n|t^        jj                  k(  rdF}ndC}|jm                  |dG|¬H«      ƒ d{  –—†  Œí n*|jm                  dIdGt^        jP                  ¬H«      ƒ d{  –—†  |�Zto        jp                  |jX                  js                  «       «       to        jp                  |jX                  ju                  «       «       |jX                  j\                  xs g }tw        |«      }d|dJdKœS t	        dLddM|› dN�i¬«      ‚|dOk(  �r"dO|jW                  d>dP«      vrddM|› dN�i}t	        dL|¬«      ‚ty        «       }|€ddQi}t	        dL|¬«      ‚dRt^        jP                  jz                  › dSt}        j~                  «       j�                  dT«      › dU�} |jX                  j‚                  j…                  |t‡        tˆ        «      t‹        jŒ                  t�        | «      «      ¬V«      ƒ d{  –—† }!|!j�                  dk\  r+ddW|!j�                  › dX|!j’                  › �i}"t	        dY|"¬«      ‚ddZdœ}#|#S |d[k(  r�t•        d\tL        jN                  d]| jD                  xs d5d^dd| jF                  t—        j˜                  d_«      | jJ                  ¬`«
      }$|jX                  j›                  |$¬a«      ƒ d{  –—†  ddbdœS y7 �Œ:7 �Œ
7 �Œ¬7 �Œn7 �Œ07 �Œ|7 �Œü7 �ŒÔ7 �Œ“7 �Œi7 Œê7 Œ*# tœ        $ rö}%tŸ        j                   dc|%«       tŸ        j¢                  t¥        j¦                  «       «       t%        |%t        «      rPt©        t        |%ddde|%› df�«      tª        j¬                  t        |%dgdh«      t        |%dit:        j®                  «      ¬j«      ‚t%        |%t¨        «      r|%‚t©        dkt±        |%«      z   tª        j¬                  t        |%dgdh«      t:        j®                  ¬j«      ‚d}%~%ww xY w­w)lzØ
    Use this admin-only endpoint to check if the service is healthy.

    Example:
    ```
    curl -L -X GET 'http://0.0.0.0:4000/health/services?service=datadog'     -H 'Authorization: Bearer sk-1234'
    ```
    r   )Úgeneral_settingsÚprisma_clientÚproxy_logging_objNr8   r9   zService must be specified.r:   )rg   rn   rh   ri   rj   rk   rl   rm   ro   ÚotelÚcustom_callback_apiÚ	langsmithrp   Údatadog_metricsrq   rr   rs   rt   ru   rv   z!Service must be in list. Service=z not in FTr_   rl   ro   rr   rh   z"openai/litellm-mock-response-modelÚuserzHey, how's it going?)ÚroleÚcontentzlitellm:/health/serviceszThis is a mock response)ÚmodelÚmessagesr•   Úmock_responseÚsuccesszMock LLM request made - check ú.)r   r€   rp   )ÚDataDogLoggerr   Ú	unhealthyÚerror_messagezDatadog is healthyr”   )ÚDatadogMetricsLogger)Ú"get_custom_logger_compatible_class)Ústart_periodic_flushzDatadog Metrics is healthyrs   )ÚArizeLoggerzArize is healthyrt   )ÚGalileoObservezGalileo is healthy)ÚLangFuseLoggerz'Mock LLM request made - check langfuse.ru   z7Only proxy admins can trigger the New Relic test event.)ÚNewRelicLoggeru(   New Relic is healthy â€” test event sentrm   Ú é   )ÚtokenÚspendÚ
max_budgetÚuser_idÚ	key_aliasÚteam_idÚevent_groupÚuser_budget)ÚtypeÚ	user_inforv   )Ú	SQSLoggerrj   rg   Úalertingzdefault test messagezLLM Exception test alertzLLM Too Slow test alertzLLM Requests Hanging test alertzBudget Alert test alertzDB Exception test alertz!Outage Alert Exception test alertzDaily Reports test alertÚLow)r€   ÚlevelÚ
alert_typez"This is a test slack alert messagezBMock Slack Alert sent, verify Slack Alert Received on your channel)r   Úalert_typesr€   i¦  ú"z=" not in proxy config: general_settings. Unable to test this.rk   rV   z2MS_TEAMS_WEBHOOK_URL not set. Unable to test this.zAlert type: `z`
Level: `Low`
Timestamp: `z%H:%M:%Sz1`

Message: This is a test MS Teams alert message)ÚurlÚheadersÚdataz!MS Teams webhook returned status z: éô  zHMock MS Teams Alert sent, verify MS Teams Alert Received in your channelrn   Úkey_createdzTest Email AlertzNEmail Test key (This is only a test alert key. DO NOT USE THIS IN PRODUCTION.)ÚTEST_EMAIL_ADDRESS)
Úeventr¯   Úevent_messager©   r­   rª   r«   r¬   Ú
user_emailr®   )Úwebhook_eventz2Mock Email Alert sent, verify Email Alert ReceivedzMlitellm.proxy.proxy_server.health_services_endpoint(): Exception occured - %sr<   zAuthentication Error(ú)rX   ÚNoner;   )r€   r±   rX   ÚcodezAuthentication Error, )YÚlitellm.proxy.proxy_serverrŽ   r�   r�   r   ÚservicesÚlitellmÚsuccess_callbackÚgetattrre   ÚacompletionÚ$litellm.integrations.datadog.datadogr�   Úasync_health_checkÚ,litellm.integrations.datadog.datadog_metricsr    Ú*litellm.litellm_core_utils.litellm_loggingr¡   r=   Ú litellm.integrations.arize.arizer£   Úlitellm.integrations.galileor¤   Ú&litellm.integrations.langfuse.langfuser¥   ÚLangfuseÚ
auth_checkÚ
completionÚ_is_proxy_adminr   ÚHTTP_403_FORBIDDENÚ&litellm.integrations.newrelic.newrelicr¦   r   r©   r¬   r­   r®   r   ÚKEYÚbudget_alertsÚlitellm.integrations.sqsr³   ÚgetÚslack_alerting_instanceÚalert_to_webhook_urlr¸   r   Úllm_exceptionsÚllm_too_slowÚllm_requests_hangingÚdb_exceptionsÚoutage_alertsÚdaily_reportsÚalerting_handlerÚasyncioÚcreate_taskÚsend_monthly_spend_reportÚsend_weekly_spend_reportrB   r   rJ   r   ÚnowÚstrftimeÚasync_http_handlerÚpostr>   r   ÚjsonÚdumpsr   r;   Útextr$   ÚosÚgetenvÚ&send_key_created_or_user_invited_emailÚ	Exceptionr   r9   ÚdebugÚ	tracebackÚ
format_excr!   r    Ú
auth_errorÚHTTP_500_INTERNAL_SERVER_ERRORrC   )&r‹   rŒ   rŽ   r�   r�   Úservice_in_success_callbacksÚcbÚcb_idÚ_r�   Údatadog_loggerÚresponser    r¡   Údatadog_metrics_loggerr£   Úarize_loggerr¤   Úgalileo_loggerr¥   Úlangfuse_loggerr¦   Únewrelic_loggerr²   r³   Ú
sqs_loggerr·   Útest_messager¸   Únot_configured_detailÚms_teams_webhook_urlÚmissing_webhook_detailÚms_teams_test_messageÚms_teams_responseÚdelivery_failed_detailÚms_teams_successrÃ   Úes&                                         rK   Úhealth_services_endpointr  à   sŠ	  è ø€ ð$l
÷	
ñ 	
ð ˆ?Ü¨C¸ÐB^Ð8_Ô`Ð`àð 
ñ 
ô,  ØØÐ#DÀWÀIÈXÔV^ÐU_Ð!`Ðaôð ð
 (-Ð$Ø”g×.Ñ.Ñ.Ø+/Ñ(ä×.Ñ.ò �Ü˜2˜°Ó5¸Ò@Ø37Ð0ÙÜ/°Ó3�Ø˜GÓ#Ø37Ð0Ùðð �{Ò"Ø˜,Ò&Ø˜-Ò'Ù,°¸JÒ1Fä×)Ñ)Ø:Ø#)Ð6LÑMÐNØ/Ø7ô	÷ ˆAð $Ø;¸G¸9ÀAÐFñð ð ˜	Ò!ÝJá$1£OˆNØ+×>Ñ>Ó@×@ˆHà" 8Ñ,Ø9AÀ(Ñ9KÈ{Ò9Z˜H _Ñ5ñð à`tñð ð Ð)Ò)õõñ &HÐHYÓ%ZÐ"Ø%Ð-Ù)=ÐSXÔ)YÐ&ÜÐ4Ð6JÔKÐKÐKØ3×FÑFÓH×HˆHà" 8Ñ,à19¸(Ñ1CÀ{Ò1R�H˜_Ñ-ñð ð Yuñð ð ˜ÒÝDá"-£-ˆLØ)×<Ñ<Ó>×>ˆHà" 8Ñ,Ø9AÀ(Ñ9KÈ{Ò9Z˜H _Ñ5ñð à`rñð ð ˜	Ò!ÝCá$2Ó$4ˆNØ+×>Ñ>Ó@×@ˆHà" 8Ñ,Ø9AÀ(Ñ9KÈ{Ò9Z˜H _Ñ5ñð à`tñð ð ˜
Ò"ÝMá%3Ó%5ˆOØ×$Ñ$×/Ñ/Ô1Ü×"Ñ"Ø:Ø#)Ð6LÑMÐNØ/Ø7ô	ˆAð $ØDñð ð ˜
Ò"Ü"Ð#4Ô5Ü#Ü &× 9Ñ 9Ø#Ð%^Ð_ôð õ Ná%3Ó%5ˆOØ,×?Ñ?ÓA×AˆHà" 8Ñ,ð   Ñ)¨[Ò8ð ˜_Ñ-ñð ð
 Dñð ð �iÒÜ'Ø'×-Ñ-Ò3°ØØØ)×1Ñ1Ø+×5Ñ5Ø)×1Ñ1Ü.×2Ñ2ô ˆIð $×1Ñ1Ø"Ø#ð 2ó ÷ ñ ð ˜ÒÝ:á )£ˆJØ'×:Ñ:Ó<×<ˆHà" 8Ñ,Ø# OÑ4ñð ð
 �gÒ Ð,AÓ!AØÐ*×.Ñ.¨z¸2Ó>Ò>ð %×<Ñ<×QÑQÑ]Ø&7×&OÑ&O×&dÑ&dò ˜
ð .×EÑE×QÑQÐ]Ø *Ð2C×2[Ñ2[×2gÑ2gÑ gà$à'=˜Ø%¬×)AÑ)AÒAØ+E™LØ'¬9×+AÑ+AÒAØ+D™LØ'¬9×+IÑ+IÒIØ+L™LØ'¬9×+BÑ+BÒBØ+D™LØ'¬9×+BÑ+BÒBØ+D™LØ'¬9×+BÑ+BÒBØ+N™LØ'¬9×+BÑ+BÒBØ+E™Là+D˜Là/×@Ñ@Ø$0¸È*ð Aó ÷ ñ ñ5ð< ,×<Ñ<Ø DØ#Ü#,×#:Ñ#:ð =ó ÷ ð ð !Ð,Ü×'Ñ'Ð(9×(QÑ(Q×(kÑ(kÓ(mÔnÜ×'Ñ'Ð(9×(QÑ(Q×(jÑ(jÓ(lÔmà/×GÑG×SÑSÒYÐWY�Ü" ;Ó/�à'Ø#.Øcñð ô $Ø #Ø# q¨¨	Ð1nÐ%oÐpôð ð �jÓ ØÐ!1×!5Ñ!5°jÀ"Ó!EÑEà˜q  	Ð)fÐgðIÐ%ô $°Ð<QÔRÐRÜ*BÓ*DÐ Ø#Ð+àÐQðJÐ&ô $°Ð<RÔSÐSà¤	× 7Ñ 7× =Ñ =Ð>ð ?Ü'Ÿ|™|›~×6Ñ6°zÓBÐCð DAðAð "ð
 .?×-VÑ-V×-iÑ-i×-nÑ-nØ(ÜÔ3Ó4Ü—Z‘ZÔ 6Ð7LÓ MÓNð .oó .÷ (Ðð
 !×,Ñ,°Ò3àÐ@ÐAR×A^ÑA^Ð@_Ð_aÐbs×bxÑbxÐayÐzðJÐ&ô $°Ð<RÔSÐSà#ØeñDÐð $Ð#Ø�gÒÜ#/Ø#Ü.×2Ñ2Ø0Ø'×-Ñ-Ò3°ØjØØØ)×1Ñ1ÜŸ9™9Ð%9Ó:Ø)×1Ñ1ô$ˆMð $×;Ñ;×bÑbØ+ð có ÷ ð ð
 $ØOñð ð' ðWùð Aùð" Iùð ?ùð Aùð: Bùð(ùð =ùðJùðùðN(øð<ùô ò 
Ü×"Ñ"Ð#rÐtuÔvÜ×"Ñ"¤9×#7Ñ#7Ó#9Ô:Ü�aœÔ'Ü Ü  8Ð/DÀQÀCÀqÐ-IÓJÜ$×/Ñ/Ü˜a ¨&Ó1Ü˜Q ¬v×/TÑ/TÓUô	ð ô ˜œ>Ô*ØˆGÜØ,¬s°1«vÑ5Ü ×+Ñ+Ü˜!˜W fÓ-Ü×6Ñ6ô	
ð 	
ûð
üsÅ  ‚`$„B\" Â;\" Ã\ Ã\" Ã`$Ã%\" Ã9\Ã:\" Ä`$Ä\" Ä`$ÄA\" Å\Å\" Å1`$Å2\" Å5`$Å6%\" Æ\	Æ\" Æ2`$Æ3\" Æ6`$Æ7%\" Ç\Ç\" Ç3`$Ç4\" Ç7`$Ç8A\" É`$ÉA\" Ê\Ê\" Ê*`$Ê+\" Ê.`$Ê/A'\" Ì\Ì*\" Í\Í\" Í`$ÍD4\" Ò\Ò,\" Ò2\Ò3B
\" Ô=`$Ô>C5\" Ø3\Ø4A\" Ù8`$Ù9A<\" Û5\ Û6\" Û>`$Ü \" Ü\" Ü\" Ü	\" Ü\" Ü\" Ü\" Ü\" Ü\" Ü\" Ü\" Ü \" Ü"	`!Ü+C1`à`!à!`$c                 ó„  — | j                   | j                  | j                  | j                  | j                  | j
                  | j                  | j                  | j                  | j                  | j                  r| j                  j                  «       nd| j                  r| j                  j                  «       dœS ddœS )z9Convert health check database record to dictionary formatN)Úhealth_check_idÚ
model_nameÚmodel_idr   Úhealthy_countÚunhealthy_countrŸ   Úresponse_time_msÚdetailsÚ
checked_byÚ
checked_atÚ
created_at)r  r  r  r   r  r  rŸ   r  r  r  r  Ú	isoformatr  )Úchecks    rK   Ú_convert_health_check_to_dictr  !  s©   € ð !×0Ñ0Ø×&Ñ&Ø—N‘NØ—,‘,Ø×,Ñ,Ø ×0Ñ0Ø×,Ñ,Ø!×2Ñ2Ø—=‘=Ø×&Ñ&Ø6;×6FÒ6F�e×&Ñ&×0Ñ0Ô2ÈDØ6;×6FÒ6F�e×&Ñ&×0Ñ0Ó2ñð ð MQñð rM   c                  óP   — ddl m}  | €t        t        j                  ddi¬«      ‚| S )zIHelper to check if prisma_client is available and raise appropriate errorr   ©r�   r9   zDatabase not initializedr:   )rÇ   r�   r   r   rú   r   s    rK   Ú_check_prisma_clientr!  3  s2   € å8àÐÜÜ×=Ñ=ØÐ7Ð8ô
ð 	
ð ÐrM   r  Úhealthy_endpointsÚunhealthy_endpointsÚ
start_timer¬   r  c              ƒ   ód  K  — 	 |r(|d   j                  d«      rt        |d   d   «      dd nd}| j                  |||rdndt        |«      t        |«      |t	        j                  «       |z
  dz  d|¬«	      ƒ d{  –—†  y7 Œ# t
        $ r!}t        j                  d	||«       Y d}~yd}~ww xY w­w)
z8Helper function to save health check results to databaser   r9   Nr½   Úhealthyrž   éè  ©	r  r  r   r  r  rŸ   r  r  r  z8Failed to save health check to database for model %s: %s)rÝ   rC   Úsave_health_check_resultÚlenÚtimerõ   r   Úwarning)	r�   r  r"  r#  r$  r¬   r  rŸ   Údb_errors	            rK   Ú_save_health_check_to_dbr.  ?  sÍ   è ø€ ðwñ #Ð':¸1Ñ'=×'AÑ'AÀ'Ô'Jô Ð# AÑ& wÑ/Ó0°°#Ñ6àð 	ð ×4Ñ4Ø!ØÙ 1‘9°{ÜÐ/Ó0ÜÐ 3Ó4Ø'Ü"Ÿi™i›k¨JÑ6¸$Ñ>ØØð 5ó 

÷ 
	
ò 
	
ùô ò wÜ×$Ñ$Ð%_ÐakÐmu×vÑvûðwüsA   ‚B0„A7B Á;BÁ<B Â B0ÂB Â	B-ÂB(Â#B0Â(B-Â-B0Ú
model_listc                 ó  — i }| D ]  }|j                  di «      }|j                  d«      }|j                  d«      }|j                  di «      }|j                  d«      }|sŒ]|sŒ`||vrg ||<   ||   j                  ||dœ«       Œ� |S )a2  
    Build a mapping from model parameter to model info (model_name, model_id).

    Multiple models might share the same model parameter, so we use a list.

    Args:
        model_list: List of model configurations

    Returns:
        Dictionary mapping model parameter to list of model info dicts
    Ú
model_infor  r?   Úlitellm_paramsr˜   )r  r  )rÝ   rF   )r/  Úmodel_param_to_infor˜   r1  r  r  r2  Úmodel_params           rK   Ú"_build_model_param_to_info_mappingr5  a  s¥   € ð (*ÐØò ˆØ—Y‘Y˜|¨RÓ0ˆ
Ø—Y‘Y˜|Ó,ˆ
Ø—>‘> $Ó'ˆØŸ™Ð#3°RÓ8ˆØ$×(Ñ(¨Ó1ˆâš:ØÐ"5Ñ5Ø35Ð# KÑ0Ø Ñ,×3Ñ3à",Ø (ñõðð  ÐrM   r3  c                 óÐ  — i }|D ]T  }|j                  d«      }|sŒ|| v sŒ| |   D ]1  }|d   |d   f}||vr|d   |d   ddddœ||<   ||   dxx   dz  cc<   Œ3 ŒV |D ]…  }|j                  d«      }|j                  d	«      }|sŒ(|| v sŒ-| |   D ]Q  }|d   |d   f}||vr|d   |d   ddddœ||<   ||   d
xx   dz  cc<   ||   d   rŒ;|sŒ>t        |«      dd ||   d<   ŒS Œ‡ |S )aÀ  
    Aggregate health check results per unique model.

    Uses (model_id, model_name) as key, or (None, model_name) if model_id is None.

    Args:
        model_param_to_info: Mapping from model parameter to model info
        healthy_endpoints: List of healthy endpoint results
        unhealthy_endpoints: List of unhealthy endpoint results

    Returns:
        Dictionary mapping (model_id, model_name) to aggregated health check results
    r˜   r  r  r   N)r  r  r  r  rŸ   r  r¨   r9   r  rŸ   r½   )rÝ   rC   )	r3  r"  r#  Úmodel_resultsÚendpointr4  r1  r\   rŸ   s	            rK   Ú_aggregate_health_check_resultsr9  �  sz  € ð$ €Mð &ò 9ˆØ—l‘l 7Ó+ˆÚ˜;Ð*=Ò=Ø1°+Ñ>ò 
9�
Ø! *Ñ-¨z¸,Ñ/GÐH�Ø˜mÑ+à&0°Ñ&>Ø$.¨zÑ$:Ø)*Ø+,Ø)-ñ*�M #Ñ&ð ˜cÑ" ?Ó3°qÑ8Ô3ñ
9ð9ð  (ò SˆØ—l‘l 7Ó+ˆØ Ÿ™ WÓ-ˆÚ˜;Ð*=Ò=Ø1°+Ñ>ò S�
Ø! *Ñ-¨z¸,Ñ/GÐH�Ø˜mÑ+à&0°Ñ&>Ø$.¨zÑ$:Ø)*Ø+,Ø)-ñ*�M #Ñ&ð ˜cÑ"Ð#4Ó5¸Ñ:Ó5à$ SÑ)¨/Ó:º}Ü:=¸mÓ:LÈTÈcÐ:R�M #Ñ& Ò7ñSð	Sð& ÐrM   r7  Úlatest_checks_mapr  c              ƒ   óò  K  — |j                  «       D ]à  }|d   dkD  rdnd}d}|d   r|d   n|d   }||v rf||   }	|	j                  |k(  rR|	j                  rFddlm}
m}  |
j
                  |j                  «      |	j                  z
  j                  «       }|d	k  rd
}|sŒ�t        j                  | j                  |d   |d   ||d   |d   |d   t        j                  «       |z
  dz  d|¬«	      «       Œâ y­w)a|  
    Save health check results to database, but only if status changed or >1 hour since last save.

    OPTIMIZATION: Only saves to database if the status has changed from the last saved check.
    This dramatically reduces database writes when health status remains stable.

    - Stable systems: ~1 write/hour per model (instead of 12 writes/hour with 5-min intervals)
    - Status changes: Immediate write (no delay)
    - Result: ~92% reduction in DB writes for stable systems, while maintaining real-time updates on changes

    Args:
        prisma_client: Database client
        model_results: Dictionary of aggregated health check results per model
        latest_checks_map: Dictionary mapping model_id/model_name to latest health check
        start_time: Start time of health check for calculating response time
        checked_by: Identifier for who/what performed the check
    r  r   r&  rž   Tr  r  )r   Útimezonei  Fr  rŸ   r'  Nr(  )rA   r   r  r   r<  rë   ÚutcÚtotal_secondsrç   rè   r)  r+  )r�   r7  r:  r$  r  ÚresultÚ
new_statusÚshould_saveÚ
lookup_keyÚ
last_checkr   r<  Útime_since_last_checks                rK   Ú%_save_health_check_results_if_changedrE  ¼  s   è ø€ ð0  ×&Ñ&Ó(ò !ˆØ"(¨Ñ"9¸AÒ"=‘YÀ;ˆ
ð ˆØ+1°*Ò+=�V˜JÒ'À6È,ÑCWˆ
ØÐ*Ñ*Ø*¨:Ñ6ˆJà× Ñ  JÒ.à×(Ò(ß;à-9¨X¯\©\¸(¿,¹,Ó-GÈ*×J_ÑJ_Ñ-_×,nÑ,nÓ,pÐ)ð -¨tÒ3Ø&+˜âÜ×ÑØ×6Ñ6Ø% lÑ3Ø# JÑ/Ø%Ø"(¨Ñ"9Ø$*Ð+<Ñ$=Ø"(¨Ñ"9Ü&*§i¡i£k°JÑ&>À$Ñ%FØ Ø)ð 7ó 
õñ+!ùs   ‚BC7Â AC7c              ƒ   óp  K  — | €y	 t        |«      }t        |||«      }| j                  «       ƒ d{  –—† }i }	|D ]0  }
|
j                  r|
j                  n|
j                  }||	vsŒ,|
|	|<   Œ2 t        | ||	||«      ƒ d{  –—†  y7 ŒS7 Œ# t        $ r }t        j                  d|«       Y d}~yd}~ww xY w­w)a³  
    Save background health check results to database for each model.

    Maps health check endpoints back to their original models to get model_name and model_id.
    Aggregates results per unique model (by model_id if available, otherwise model_name).

    OPTIMIZATION: Only saves to database if the status has changed from the last saved check.
    This dramatically reduces database writes when health status remains stable.
    Nz7Failed to save background health checks to database: %s)	r5  r9  Úget_all_latest_health_checksr  r  rE  rõ   r   r,  )r�   r/  r"  r#  r$  r  r3  r7  Úlatest_checksr:  r  r\   r-  s                rK   Ú$_save_background_health_checks_to_dbrI  ø  sá   è ø€ ð" ÐØðjä%GÈ
Ó%SÐô  ?ØØØó 
ˆð &3×%OÑ%OÓ%Q×QˆØ#%ÐØ"ò 	/ˆEà$)§N¢N�%—.’.¸×8HÑ8HˆCØÐ+Ò+Ø).Ð! #Ò&ð		/ô 4ØØØØØó
÷ 	
ñ 	
ð  Røð	
ùô ò jÜ×$Ñ$Ð%^Ð`h×iÑiûðjüsV   ‚B6‡+B
 ²B³3B
 Á'B
 Â BÂB
 ÂB6ÂB
 ÂB
 Â
	B3ÂB.Â)B6Â.B3Â3B6Ú_PROXY_ADMIN_ROLESc                 ód   — | j                   }|€yt        |d«      r|j                  n|}|t        v S )a,  
    Return True if the caller has a proxy-admin role (full or view-only).

    user_role on UserAPIKeyAuth can be either a LitellmUserRoles enum or its
    string value depending on how the auth path constructed the object, so we
    compare against the raw value rather than the enum identity.
    FrJ   )Ú	user_rolera   rJ   rJ  )r‹   r–   Ú
role_values      rK   r×   r×   9  s7   € ð $×-Ñ-€DØ€|ØÜ&-¨d°GÔ&<˜Ÿ
š
À$€JØÔ+Ð+Ð+rM   r?  c                 óF  — t        | «      }t        t        «      }dD ]t  }|j                  |«      }t	        |t
        «      sŒ%|D ���cg c]=  }t	        |t         «      r)|j                  «       D ��ci c]  \  }}||vsŒ||“Œ c}}n|‘Œ? c}}}||<   Œv |S c c}}w c c}}}w )ab  
    Return a copy of the /health response with provider routing fields
    (``api_base``, ``api_version``) removed from each healthy/unhealthy
    endpoint entry. Used to hide those fields from non-admin callers while
    still showing them which deployments they own and whether each one is
    healthy. Proxy admins receive the unmodified result.
    )r"  r#  )r>   Úsetr)   rÝ   r=   rB   r[   )r?  ÚoutÚdropr\   ÚepsÚepÚkÚvs           rK   Ú+_strip_admin_only_fields_from_health_resultrV  H  s˜   € ô �f“€CÜÔ6Ó7€DØ;ò xˆØ�g‰g�c‹lˆÜ�cœ4Õ Øsv×wÐwÐmoÌ:ÐVXÔZ^ÔK_¨2¯8©8«:×G¡4 1 a¸À$º˜!˜Q™$ÔGÐegÑgÔwˆC�ŠHðxð €Jùó HùÔws   Á(B
Á0BÁ=BÂB
ÂB
r˜   c                 óV  — |s|syt        «       }| D ]”  }|j                  d«      xs i j                  d«      }|sŒ*|r||k(  r|j                  |«       ŒC|sŒF|j                  d«      xs i j                  d«      }|j                  d«      |k(  s||k(  sŒ„|j                  |«       Œ– |S )ul  
    Resolve a ``/health`` ``model`` / ``model_id`` query param to the set of
    deployment IDs the response should be scoped to.

    Mirrors the live-path semantics in ``perform_health_check()``: ``model``
    matches either the deployment's ``model_name`` alias or its
    ``litellm_params.model`` provider string. ``model_id`` matches
    ``model_info.id``.

    Both query params are validated against the supplied ``model_list``.
    Callers pass an already-scoped list (filtered to the caller's allowed
    models for non-admins, full list for admins), so a ``model_id`` that
    isn't present resolves to an empty set rather than a single-element
    set â€” preventing a non-admin from reading another deployment's cached
    health entry by guessing its ID.

    Returns ``None`` when no targeting is requested â€” callers should treat
    that as "no filter."
    Nr1  r?   r2  r˜   r  )rO  rÝ   rE   )r/  r˜   r  Ú
target_idsÚmÚdeployment_idÚlitellm_models          rK   Ú_resolve_targeted_model_idsr\  Y  s­   € ñ( ™ØÜ ›U€JØò 
.ˆØŸ™˜|Ó,Ò2°×7Ñ7¸Ó=ˆÙØÙ˜¨Ò1Ø�N‰N˜=Ô)ØÚØŸU™UÐ#3Ó4Ò:¸×?Ñ?ÀÓHˆMØ�u‰u�\Ó" eÒ+¨}ÀÓ/EØ—‘˜}Õ-ð
.ð ÐrM   ÚresultsÚallowed_model_idsc                 óD  — | j                  d«      xs g D �cg c]!  }|j                  d«      |v sŒt        |«      ‘Œ# }}| j                  d«      xs g D �cg c]!  }|j                  d«      |v sŒt        |«      ‘Œ# }}||t        |«      t        |«      dœS c c}w c c}w )u5  
    Restrict a cached background health-check result dict to endpoints whose
    model_id is in ``allowed_model_ids``.

    Endpoints without a model_id (e.g. CLI-model entries that predate the
    model_id wiring) are dropped conservatively â€” we cannot prove they belong
    to the caller, so they are excluded rather than leaked.

    Each retained endpoint is shallow-copied before being returned, so any
    downstream transform (e.g. _strip_admin_only_fields_from_health_result)
    cannot accidentally mutate the shared ``health_check_results`` cache.
    r"  r  r#  ©r"  r#  r  r  )rÝ   r>   r*  )r]  r^  rS  r&  rž   s        rK   Ú)_filter_health_check_results_by_model_idsra  ~  s¦   € ð $+§;¡;Ð/BÓ#CÒ#IÀrÖv˜BÈbÏfÉfÐU_ÓN`ÐduÒNuŒt�B�xÐv€GÐvà#ŸK™KÐ(=Ó>ÒDÀ"öØÈÏÉÐPZÓI[Ð_pÒIpŒˆR�ð€Ið ð %Ø(Ü˜W›Ü˜y›>ñ	ð ùò	 wùòs   ˜B±BÁBÁ0Bc	              ‹   óÚ   K  — t        d| |||||dœ|	¤Žƒ d{  –—† \  }
}}|�-|�|n|}|�%t        j                  t        |||
||||¬«      «       |
|t	        |
«      t	        |«      dœS 7 ŒP­w)zDHelper function to perform health check and save results to database)r/  Ú	cli_modelr˜   r  Úmax_concurrencyr  N©r  r`  rV   )r-   rç   rè   r.  r*  )r/  Útarget_modelrc  r  r�   r$  r¬   r  rd  Úperform_health_check_extrar"  r#  rþ   Úmodel_name_for_dbs                 rK   Ú_perform_health_check_and_saveri  —  s±   è ø€ ô 7Kð 7ØØØØØ'Øñ7ð %ñ7÷ 1Ñ-ÐÐ*¨Að Ð à09Ð0E¡9È<ÐØÐ(Ü×ÑÜ(Ø!Ø%Ø%Ø'ØØØ%ôô
ð /Ø2ÜÐ.Ó/ÜÐ2Ó3ñ	ð ð71ús   ‚A+˜A)™AA+c                 ól  — |r| r| S |€!t        t        j                  dd|› d�i¬«      ‚	 |j                  |¬«      }|€!t        t        j                  dd|› d�i¬«      ‚|j                  S # t        $ r>}t        j                  d||«       t        t        j                  dd|› d�i¬«      |‚d}~ww xY w)zNMap ``model_id`` (without ``model``) to ``model_name`` for live health checks.Nr9   zModel with ID z
 not foundr:   re  z,Error getting deployment for model_id %s: %s)r   r   ÚHTTP_404_NOT_FOUNDÚget_deploymentrõ   r   r9   r  )r˜   r  Ú
llm_routerÚ
deploymentr  s        rK   Ú*_health_endpoint_resolve_target_model_namero  Ç  sã   € ñ ‘uØˆØÐÜÜ×1Ñ1Ø˜~¨h¨Z°zÐBÐCô
ð 	
ðØ&×5Ñ5¸xÐ5ÓHˆ
ð ÐÜÜ×1Ñ1Ø˜~¨h¨Z°zÐBÐCô
ð 	
ð × Ñ Ð øô ò Ü×"Ñ"Ð#QÐS[Ð]^Ô_ÜÜ×1Ñ1Ø˜~¨h¨Z°zÐBÐCô
ð ð	ûðús   «A, Á,	B3Á59B.Â.B3z/healthz!Specify the model name (optional)zSpecify the model ID (optional)r   c              ƒ   óì  ‡ ‡‡K  — ddl }ddlm}m}m}m}m}	m}
m}m	}m
} t        |«      } |j                   «       }t        |||
«      }t        |«      Št        |xs |«      Šdt        dt        fˆˆˆ fd„}	 |	€N|�/t!        dg d|||||j"                  d|dœ	|¤Žƒ d{  –—† } ||«      S t%        t&        j(                  dd	i¬
«      ‚t+        j,                  |	«      }t/        |j0                  «      }t2        j4                  j6                  |v r!|j8                  �t/        |j:                  «      }t=        |«      dkD  xr t2        j>                  j6                  |v}|r.tA        |«      }|D �cg c]  }|jC                  d«      |v sŒ|‘Œ }}|rØtE        |||«      }|r­|D �ch c]J  }|jC                  d«      xs i jC                  d«      r$|jC                  d«      xs i jC                  d«      ’ŒL }}|�|n|}tG        ||«      }|€<|s:tI        jJ                  d|j"                  t/        |j0                  «      «       dg|d<    ||«      S |� |tG        ||«      «      S  ||«      S t!        d||d||||j"                  |||
dœ
|¤Žƒ d{  –—† } ||«      S 7 �Œ÷c c}w c c}w 7 Œ# tL        $ rD}tI        jN                  d|«       tI        jP                  tS        jT                  «       «       |‚d}~ww xY w­w)uš  
    ðŸš¨ USE `/health/liveliness` to health check the proxy ðŸš¨

    See more ðŸ‘‰ https://docs.litellm.ai/docs/proxy/health


    Check the health of all the endpoints in config.yaml

    To run health checks in the background, add this to config.yaml:
    ```
    general_settings:
        # ... other settings
        background_health_checks: True
    ```
    else, the health checks will be run on models when /health is called.

    To skip deployments that set ``model_info.disable_background_health_check: true``
    on ``GET /health`` as well as in the background loop, set
    ``general_settings.health_check_skip_disabled_background_models: true``.
    r   N)	rŽ   Úhealth_check_concurrencyÚhealth_check_detailsÚhealth_check_resultsÚllm_model_listrm  r�   Úuse_background_health_checksÚ
user_modelr?  r6   c                 ó˜   •— ‰r*| j                  dd«      dk(  rt        j                  ‰_        ‰r| S d‰j                  d<   t        | «      S )Nr  r   z8api_base and api_version are admin-only on this endpointzLitellm-Health-Field-Notice)rÝ   r   ÚHTTP_503_SERVICE_UNAVAILABLEr;   r»   rV  )r?  Úis_adminÚmodel_specific_requestr   s    €€€rK   Ú_post_processz&health_endpoint.<locals>._post_process  sL   ø€ ñ " f§j¡j°À!Ó&DÈÒ&IÜ#)×#FÑ#FˆHÔ ÙØˆMØ:tˆ×ÑÐ6Ñ7Ü:¸6ÓBÐBrM   )	r/  rf  rc  r  r�   r$  r¬   r  rd  r9   zModel list not initializedr:   r  r1  r?   z®health_endpoint: scoped key %s has accessible models %s but none of the matching deployments carry a model_info.id; background health-check cache will return an empty result.z™Some accessible deployments are missing model_info.id and were excluded from this response. Ask a proxy admin to populate model_info.id for these models.Úwarnings)
r/  rf  rc  r  r�   r$  r¬   r  rd  rf   zHlitellm.proxy.proxy_server.py::health_endpoint(): Exception occured - %srV   )+r+  rÇ   rŽ   rq  rr  rs  rt  rm  r�   ru  rv  r,   ro  r×   Úboolr>   ri  r¬   r   r   rú   ÚcopyÚdeepcopyrB   Úmodelsr"   Úall_team_modelsrJ   r®   Úteam_modelsr*  Úall_proxy_modelsrO  rÝ   r\  ra  r   r,  rõ   r9   rö   r÷   rø   ) r   r‹   r˜   r  r+  rŽ   rq  rr  rs  rt  rm  r�   ru  rv  Ú
_hc_filterr$  rf  r{  Ú
cli_resultÚ_llm_model_listÚaccessible_modelsÚrestrict_to_allowed_modelsÚallowed_modelsrY  Útargeted_idsr^  Ú
filter_idsÚfilteredÚrouter_resultr  ry  rz  s    `                             @@rK   Úhealth_endpointrŽ  ä  sZ  úè ø€ ó6 ÷
÷ 
õ 
ô IÐIYÓZ€JØ!˜Ÿ	™	›€JäDÀUÈHÐV`Óa€Lä%Ð&7Ó8€HÜ$(¨Ò):°(Ó$;ÐðCœdð C¤t÷ Cð"oØÐ!àÐ%Ü*Hð +Ø!Ø!%Ø(Ø0Ø"/Ø)Ø-×5Ñ5Ø!Ø$<ñ+ð !ñ+÷ %�
ñ % ZÓ0Ð0ÜÜ"×AÑAØÐ!=Ð>ôð ô Ÿ-™-¨Ó7ˆô" !Ð!2×!9Ñ!9Ó:ÐÜ×,Ñ,×2Ñ2Ð6GÑGÐL]×LeÑLeÐLqÜ $Ð%6×%BÑ%BÓ CÐäÐ!Ó" QÑ&ÒlÔ+<×+MÑ+M×+SÑ+SÐ[lÐ+lð 	#ñ &Ü$'Ð(9Ó$:ˆNØ*9Öc Q¸Q¿U¹UÀ<Ó=PÐTbÒ=bšqÐcˆOÐcÙ'ô #>¸oÈuÐV^Ó"_ˆLÙ)ð -ö,àØŸ™˜lÓ+Ò1¨r×6Ñ6°tÔ<ð —U‘U˜<Ó(Ò.¨B×3Ñ3°DÕ9ð,Ð!ð ,ð 5AÐ4L¡LÐRc�
Ü"KÐL`ÐblÓ"m�ØÐ'Ñ0Aô )×0Ñ0ðUð *×1Ñ1ÜÐ.×5Ñ5Ó6ôðFð,�H˜ZÑ(ñ
 % XÓ.Ð.ØÐ'ñ %Ô%NÐOcÐeqÓ%rÓsÐsÙ Ð!5Ó6Ð6ä)Gð *Ø*Ø)ØØ,Ø+Ø%Ø)×1Ñ1Ø!Ø 8Ø!ñ*ð ñ*÷ $ˆMñ ! Ó/Ð/ðO%ûòT dùò,ðL$ùô ò Ü×"Ñ"Ð#mÐopÔqÜ×"Ñ"¤9×#7Ñ#7Ó#9Ô:ØˆûðüsŸ   …A2K4Á8&J$ ÂJÂJ$ Â*K4Â+CJ$ Å,JÆJÆ	J$ Æ AJÇ/AJ$ ÉK4É	J$ ÉK4ÉJ$ É$K4É%#J$ ÊJ"Ê	J$ ÊK4ÊJ$ ÊJ$ Ê$	K1Ê-?K,Ë,K1Ë1K4z/health/historyzFilter by specific model namez$Filter by status (healthy/unhealthy)éd   zNumber of records to returnr¨   r'  )rŠ   ÚgeÚlezNumber of records to skip)rŠ   r�  Ústatus_filterÚlimitÚoffsetc              ƒ   óF  K  — t        «       }	 |j                  ||||¬«      ƒ d{  –—† }|D �cg c]  }t        |«      ‘Œ }}|t        |«      ||dœS 7 Œ,c c}w # t        $ r;}	t        j                  d|	«       t        t        j                  dd|	› �i¬«      ‚d}	~	ww xY w­w)zp
    Get health check history for models

    Returns historical health check data with optional filtering.
    )r  r“  r”  r’  N)Úhealth_checksÚtotal_recordsr“  r”  z&Error getting health check history: %sr9   z)Failed to retrieve health check history: r:   )
r!  Úget_health_check_historyr  r*  rõ   r   r9   r   r   rú   )
r‹   r˜   r’  r“  r”  r�   Úhistoryr  Úhistory_datar  s
             rK   Úhealth_check_history_endpointr›  ˜  sÉ   è ø€ ô 0Ó1€Mð
Ø,×EÑEØØØØ'ð	  Fó  
÷ 
ˆð RYÖYÈÔ<¸UÕCÐYˆÐYð *Ü  Ó.ØØñ	
ð 	
ð
úò Zøô ò 
Ü×"Ñ"Ð#KÈQÔOÜÜ×=Ñ=ØÐHÈÈÐLÐMô
ð 	
ûð
üsI   ‚B!ŽA ¦A§A ¯AÁA ÁB!ÁA ÁA Á	BÁ#6BÂBÂB!z/health/latestc              ƒ   ó~  K  — t        «       }	 |j                  «       ƒ d{  –—† }|D �ci c]0  }|j                  r|j                  n|j                  t	        |«      “Œ2 }}|t        |«      dœS 7 ŒMc c}w # t        $ r;}t        j                  d|«       t        t        j                  dd|› �i¬«      ‚d}~ww xY w­w)z|
    Get the latest health check status for all models

    Returns the most recent health check result for each model.
    N)Úlatest_health_checksÚtotal_modelsz&Error getting latest health checks: %sr9   z)Failed to retrieve latest health checks: r:   )r!  rG  r  r  r  r*  rõ   r   r9   r   r   rú   )r‹   r�   rH  r  Úchecks_datar  s         rK   Úlatest_health_checks_endpointr   À  sÍ   è ø€ ô 0Ó1€Mð
Ø%2×%OÑ%OÓ%Q×Qˆð
 'ö
àð  %Ÿ~š~ˆU�^Š^°5×3CÑ3CÔFcÐdiÓFjÑjð
ˆð 
ð %0Ü Ó,ñ
ð 	
ð  Rúò
øô ò 
Ü×"Ñ"Ð#KÈQÔOÜÜ×=Ñ=ØÐHÈÈÐLÐMô
ð 	
ûð
üsI   ‚B=ŽA6 ¡A/¢A6 ª5A1ÁA6 Á.B=Á/A6 Á1A6 Á6	B:Á?6B5Â5B:Â:B=z/health/shared-statusc              ƒ   ó8  K  — ddl m}m} |sdddœS |€dddd	œS 	 dd
lm}  ||¬«      }|j                  «       ƒ d{  –—† }d|dœS 7 Œ	# t        $ rE}t        j                  d|«       t        t        j                  j                  dd|› �i¬«      ‚d}~ww xY w­w)z›
    Get the status of shared health check coordination across pods.

    Returns information about Redis connectivity, lock status, and cache status.
    r   )Úredis_usage_cacheÚuse_shared_health_checkFz"Shared health check is not enabled)Úshared_health_check_enabledr€   NTzRedis is not configured)r¤  Úredis_availabler€   )ÚSharedHealthCheckManager)Úredis_cache)r¤  r   z,Error getting shared health check status: %sr9   z/Failed to retrieve shared health check status: r:   )rÇ   r¢  r£  Ú<litellm.proxy.health_check_utils.shared_health_check_managerr¦  Úget_health_check_statusrõ   r   r9   r   Úfastapir   rú   )r‹   r¢  r£  r¦  Úshared_health_managerÚhealth_statusr  s          rK   Ú#shared_health_check_status_endpointr­  à  sÄ   è ø€ ÷ Vá"à+0Ø;ñ
ð 	
ð
 Ð à+/Ø$Ø0ñ
ð 	
ð
õ	
ñ (@Ø)ô(
Ðð &;×%RÑ%RÓ%T×TˆØ/3¸}ÑMÐMð  Uùäò 
Ü×"Ñ"Ð#QÐSTÔUÜÜŸ™×EÑEØÐNÈqÈcÐRÐSô
ð 	
ûð
üs9   ‚B›"A	 ½A¾A	 ÁBÁA	 Á		BÁA BÂBÂBc                  ó8  — ddl m} m} |xs | j                  }|€Rt	        | dd «      rEt	        | dd «      r8	 | j                  | j                  | j                  ¬«      }|du r| j                  }|€y t        t        t        t        f   |«      S # t        $ r Y Œ+w xY w)Nr   )Ú_license_checkÚpremium_user_dataÚlicense_strÚ
public_key)r²  Úlicense_keyT)rÇ   r¯  r°  Úairgapped_license_datarË   Ú"verify_license_without_api_requestr²  r±  rõ   r   r>   rC   r   )r¯  r°  Úlicense_dataÚverification_results       rK   Ú_read_license_datar¸    s¬   € ßLà1BÒ1kÀn×FkÑFk€Lð 	ÐÜ�N M°4Ô8Ü�N L°$Ô7ð	Ø)7×)ZÑ)ZØ)×4Ñ4Ø*×6Ñ6ð *[ó *Ðð # dÑ*Ø-×DÑD�ð ÐØÜ””Sœ#�X‘ Ó-Ð-øô ò 	Ùð	ús   ¶7B Â	BÂBr¶  c                 óh   — | j                  d«      }t        |t        «      rt        |«      S |€g S |gS )NÚallowed_features)rÝ   r=   rB   )r¶  Úraw_allowed_featuress     rK   Ú_read_allowed_featuresr¼  $  s?   € Ø".×"2Ñ"2Ð3EÓ"FÐÜÐ&¬Ô-ÜÐ(Ó)Ð)ØÐ#Øˆ	Ø Ð!Ð!rM   z/health/licensec              ƒ   ó  K  — ddl m}m} t        «       }t	        t        |dd«      «      }|rdnd}|€||dg dddœdœS |j                  d	«      }|j                  d
«      }|j                  d«      }|||t        |«      ||dœdœS ­w)zNReturn metadata about the configured LiteLLM license without exposing the key.r   )r¯  Úpremium_userr±  NÚ
enterpriseÚ	community)Ú	max_usersÚ	max_teams)Úhas_licenseÚlicense_typeÚexpiration_daterº  ÚlimitsrÅ  rÁ  rÂ  )rÇ   r¯  r¾  r¸  r}  rË   rÝ   r¼  )	r‹   r¯  r¾  r¶  rÃ  rÄ  rÅ  rÁ  rÂ  s	            rK   Úhealth_license_endpointrÇ  -  s²   è ø€ ÷ Hä,Ó.€LÜœg n°mÀTÓJÓK€KÙ*6™,¸K€LàÐà&Ø(Ø#Ø "à!Ø!ññ	
ð 		
ð *×-Ñ-Ð.?Ó@€OØ#×'Ñ'¨Ó4€IØ#×'Ñ'¨Ó4€Ið #Ø$Ø*Ü2°<Ó@à"Ø"ñ
ñ	ð 	ùs   ‚BBc                   ó"   — e Zd ZU eed<   eed<   y)ÚDBHealthCacher   Úlast_updatedN)rz   r{   r|   rC   r}   r   rV   rM   rK   rÉ  rÉ  X  s   … ØƒKØÔrM   rÉ  Úunknown©r   rÊ  Údb_health_cacheg       @Ú"DB_READINESS_CHECK_TIMEOUT_SECONDSg      @Ú#DB_READINESS_PROBE_DEADLINE_SECONDSc               ƒ   ó°   K  — 	 t        j                  t        «       t        ¬«      ƒ d {  –—† S 7 Œ# t         j                  $ r dt
        d   dœcY S w xY w­w)N©ÚtimeoutÚdisconnectedrÊ  rÌ  )rç   Úwait_forÚ$_db_health_readiness_check_unboundedrÏ  ÚTimeoutErrorrÍ  rV   rM   rK   Ú_db_health_readiness_checkr×  g  sZ   è ø€ ð[Ü×%Ñ%Ü0Ó2Ü7ô
÷ 
ð 	
ð 
ùô ×Ñò [Ø(¼/È.Ñ:YÑZÒZð[üs1   ‚A„&1 ª/«1 ®A¯1 ±AÁAÁAÁAc               ƒ   ó–  K  — ddl m}  	 t        j                  «       t        d   z
  }t        d   dk(  r|t        d¬«      k  rt        S | €dt        j                  «       d	œat        S t        j                  | j                  «       t        ¬
«      ƒ d {  –—†  dt        j                  «       d	œat        S 7 Œ!# t        $ �r}dt        j                  «       d	œat        j                  |«      rÈ	 t        j                  d«       | j                  dt        t        ¬«      ƒ d {  –—†7   t        j                  | j                  «       t        ¬
«      ƒ d {  –—†7   t        j                   d«       dt        j                  «       d	œat        cY d }~S # t        $ r t        j"                  d«       Y nw xY wt        cY d }~S d }~ww xY w­w)Nr   r   rÊ  r   Ú	connectedé   )ÚsecondsrÓ  rÌ  rÑ  zE_db_health_readiness_check: health_check failed, attempting reconnectÚhealth_readiness_check)ÚreasonÚtimeout_secondsÚlock_timeout_secondsz/_db_health_readiness_check: reconnect succeededz,_db_health_readiness_check: reconnect failed)rÇ   r�   r   rë   rÍ  r   rç   rÔ  Úhealth_checkrÎ  rõ   r'   Úis_database_transport_errorr   r,  Úattempt_db_reconnectÚinfor9   )r�   Ú	time_diffr  s      rK   rÕ  rÕ  q  s€  è ø€ Ý8ð"Ü#Ÿ<™<›>¬O¸NÑ,KÑKˆ	Ü˜8Ñ$¨Ò3¸	ÄIÐVXÔDYÒ8YÜ"Ð"àÐ Ø)7ÌÏÉËÑXˆOÜ"Ð"ä×Ñ˜}×9Ñ9Ó;ÔEgÔh×hÐhØ%0Ä(Ç,Á,Ã.ÑQˆÜÐð 	iùô ó Ø%3ÄXÇ\Á\Ã^ÑTˆÜ#×?Ñ?ÀÔBð[Ü$×,Ñ,Ð-tÔuØ#×8Ñ8Ø3Ü$FÜ)Kð 9ó ÷ ñ ô
 ×&Ñ&Ø!×.Ñ.Ó0Ü>ô÷ ñ ô %×)Ñ)Ð*[Ô\à)Ü$,§L¡L£Nñ#�ô 'Õ&øÜò [Ü$×*Ñ*Ð+YÖZð[úäÕûð-üs    ‚G	Š>B8 ÁG	Á	B8 Á'G	Á(,B8 ÂB6Â B8 Â5G	Â6B8 Â8
GÃ,GÃ/4FÄ#D&Ä$1FÅEÅ6FÆGÆG	ÆF3Æ0GÆ2F3Æ3GÆ;GÆ<G	ÇGÇG	z	/settingsz/active/callbacksc               ƒ   ór  K  — ddl m} m} t        | j	                  d«      «      }t
        j                  D �cg c]  }t        |«      ‘Œ }}t
        j                  D �cg c]  }t        |«      ‘Œ }}t
        j                  D �cg c]  }t        |«      ‘Œ }}t
        j                  D �cg c]  }t        |«      ‘Œ }}t
        j                  D �cg c]  }t        |«      ‘Œ }}t
        j                  D �cg c]  }t        |«      ‘Œ }	}t
        j                  D �cg c]  }t        |«      ‘Œ }
}||z   |z   |z   |z   |	z   |
z   }|j                  }d}|rt        |t        «      rt!        |«      }|||||||	|
|t!        |«      |t
        j"                  dœS c c}w c c}w c c}w c c}w c c}w c c}w c c}w ­w)au  
    Returns a list of litellm level settings

    This is useful for debugging and ensuring the proxy server is configured correctly.

    Response schema:
    ```
    {
        "alerting": _alerting,
        "litellm.callbacks": litellm_callbacks,
        "litellm.input_callback": litellm_input_callbacks,
        "litellm.failure_callback": litellm_failure_callbacks,
        "litellm.success_callback": litellm_success_callbacks,
        "litellm._async_success_callback": litellm_async_success_callbacks,
        "litellm._async_failure_callback": litellm_async_failure_callbacks,
        "litellm._async_input_callback": litellm_async_input_callbacks,
        "all_litellm_callbacks": all_litellm_callbacks,
        "num_callbacks": len(all_litellm_callbacks),
        "num_alerting": _num_alerting,
        "litellm.request_timeout": litellm.request_timeout,
    }
    ```
    r   )rŽ   r�   r´   )r´   zlitellm.callbackszlitellm.input_callbackzlitellm.failure_callbackzlitellm.success_callbackzlitellm._async_success_callbackzlitellm._async_failure_callbackzlitellm._async_input_callbackÚall_litellm_callbacksÚnum_callbacksÚnum_alertingzlitellm.request_timeout)rÇ   rŽ   r�   rC   rÝ   rÉ   Ú	callbacksÚinput_callbackÚfailure_callbackrÊ   Ú_async_success_callbackÚ_async_failure_callbackÚ_async_input_callbackr´   r=   rB   r*  Úrequest_timeout)rŽ   r�   Ú	_alertingÚxÚlitellm_callbacksÚlitellm_input_callbacksÚlitellm_failure_callbacksÚlitellm_success_callbacksÚlitellm_async_success_callbacksÚlitellm_async_failure_callbacksÚlitellm_async_input_callbacksræ  r´   Ú_num_alertings                 rK   Úactive_callbacksrú  ›  s´  è ø€ ÷F OäÐ+×/Ñ/°
Ó;Ó<€Iô 18×0AÑ0AÖB¨1¤ A¥ÐBÐÐBÜ6=×6LÑ6LÖ%M°¤c¨!¥fÐ%MÐÐ%MÜ8?×8PÑ8PÖ'Q°1¬¨A­Ð'QÐÐ'QÜ8?×8PÑ8PÖ'Q°1¬¨A­Ð'QÐÐ'QÜ>E×>]Ñ>]Ö-^¸¬c°!­fÐ-^Ð#Ð-^Ü>E×>]Ñ>]Ö-^¸¬c°!­fÐ-^Ð#Ð-^Ü<C×<YÑ<YÖ+Z°q¬C°­FÐ+ZÐ!Ð+Zð 	Ø
!ñ	"à
#ñ	$ð $ñ	$ð *ñ		*ð
 *ñ	*ð (ñ	(ð ð (×0Ñ0€HØ€MÙ”J˜x¬Ô.Ü˜H›ˆð Ø.Ø"9Ø$=Ø$=Ø+JØ+JØ)FØ!6ÜÐ2Ó3Ø%Ü#*×#:Ñ#:ñð ùò/  CùÚ%MùÚ'QùÚ'QùÚ-^ùÚ-^ùÚ+ZùsY   ‚5F7·FÁ	F7ÁFÁ/F7ÂFÂF7Â)F#Â;F7ÃF(Ã!F7Ã5F-ÄF7ÄF2Ä-B
F7c                 óÄ   — t        | t        «      r| S 	 | j                  S # t        $ r6 	 | j                  j                  cY S # t        $ r t        | «      cY cY S w xY ww xY wrU   )r=   rC   rz   ÚAttributeErrorr`   )rc   s    rK   r_   r_   ê  sa   € Ü�(œCÔ Øˆð!Ø× Ñ Ð øÜò !ð	!Ø×%Ñ%×.Ñ.Ò.øÜò 	!Ü�x“=Ô ð	!úð!ús+   ”   	AªA¿AÁAÁAÁAÁAÚ LITELLM_DISABLE_NO_REDIS_WARNINGÚ DISABLE_NO_REDIS_WARNING_ENV_VARc               ƒ   ó²   K  — ddl m} m}m} |�y| �| j                  j
                  �yt        t        d«      du ry|€yt        |«      ƒ d{  –—† dk7  S 7 Œ­w)a/  
    Whether the UI should warn that no Redis is configured.

    Redis is what makes rate limits, budgets, router state, and cache
    invalidation consistent across workers, so a proxy running without it is
    only safe as a single worker. Both places a Redis can land count: the
    coordination cache (from a Redis response cache, general_settings.
    coordination_redis, or the REDIS_* env fallback) and the router's own
    Redis (router_settings.redis_host), which backs cooldowns and usage-based
    routing on its own. A deployment whose worker-heartbeat census proves it
    is exactly one worker needs no cross-worker coordination, so it never
    warns; when the census is unavailable or shows more than one worker, the
    warning stands unless LITELLM_DISABLE_NO_REDIS_WARNING=true silences it.
    r   ©rm  r�   r¢  NFTr¨   )	rÇ   rm  r�   r¢  Úcacher§  r4   rþ  r(   r   s      rK   Ú_show_no_redis_warningr  ú  sd   è ø€ ÷ XÑWàÐ$ØØÐ *×"2Ñ"2×">Ñ">Ð"JØÜÔ7¸Ó?À4ÑGØØÐØÜ)¨-Ó8×8¸AÑ=Ð=Ð8ús   ‚AAÁAÁAc           
   ƒ   ó0  K  — ddl m}m} 	 g }	 t        j                  D �cg c]  }t        |«      ‘Œ }}d}t        j                  �zddlm	} t        j                  j                  }t        t        j                  j                  |«      r6	 t        j                  j                  j                  «       ƒ d{  –—† }||dœ}t        j                   t#        j$                  «       «      }	t#        j&                  t        j(                  «      }
t+        «       ƒ d{  –—† }|�ft-        «       ƒ d{  –—† }| �1|d   dk7  r)t/        j0                  «       st2        j4                  | _        d	|d   |||t9        j:                  «       |	|
|d
œ	S d	d|||t9        j:                  «       |	|
|d
œ	S c c}w # t        $ r t        j                  }Y �Œ�w xY w7 �Œ# t        $ r}dt        |«      z   }Y d}~�Œ,d}~ww xY w7 Œ×7 ŒÅ# t        $ r}t=        dd|› d�¬«      ‚d}~ww xY w­w)z@
    Detailed health payload for authenticated diagnostics.
    r   )r�   ÚversionN)ÚRedisSemanticCachezindex does not exist - error: )r±   Ú
index_infor   rÙ  r&  )	r   Údbr  Úlitellm_versionÚsuccess_callbacksÚuse_aiohttp_transportÚ	log_levelÚis_detailed_debugÚshow_no_redis_warningúNot connectedi÷  zService Unhealthy (rÄ   r:   )rÇ   r�   r  rÉ   rÊ   r_   rü  r  Úlitellm.caching.cachingr  r±   r=   Ú_index_inforõ   rC   ÚloggingÚgetLevelNamer   ÚgetEffectiveLevelÚisEnabledForÚDEBUGr  r×  r'   Ú&should_allow_request_on_db_unavailabler   rx  r;   r   Ú_should_use_aiohttp_transportr   )r   r�   r  Úsuccess_callback_namesrñ  Ú
cache_typer  r  r  Úlog_level_namer  r  Údb_health_statuss                rK   Ú_get_health_readiness_detailsr    s  è ø€ ÷ BðJPà!#Ðð	>ô AH×@XÑ@XÖ%Y¸1¤m°AÕ&6Ð%YÐ"Ð%Yð ˆ
Ü�=‰=Ð$ÝBä Ÿ™×+Ñ+ˆJäœ'Ÿ-™-×-Ñ-Ð/AÔBðKÜ'.§}¡}×':Ñ':×'FÑ'FÓ'H×!H�Jð '1À
ÑK�
ô !(× 4Ñ 4´^×5UÑ5UÓ5WÓ XˆÜ#1×#>Ñ#>¼w¿}¹}Ó#MÐÜ-CÓ-E×'EÐð Ð$Ü,FÓ,H×&HÐð Ð$Ø$ XÑ.°+Ò=Ü0×WÑWÔYä'-×'JÑ'J�Ô$à#Ø& xÑ0Ø#Ø#*Ø%;Ü)9×)WÑ)WÓ)YØ+Ø%6Ø)>ñ
ð 
ð $Ø%Ø#Ø#*Ø%;Ü)9×)WÑ)WÓ)YØ+Ø%6Ø)>ñ
ð 
ùòo &ZøÜò 	>ä%,×%=Ñ%=Ó"ð	>úð  "IúÜ ò KØ!AÄCÈÃFÑ!J–JûðKúð (Føð 'IùôJ ò PÜ¨Ð6IÈ!ÈÈAÐ4NÔOÐOûðPüsÃ   ‚	HŒG4 �F( ¡F#³F( µAG4 Â+G Â7GÂ8G Â<AG4 ÄG0ÄG4 Ä,G2Ä-AG4 ÆHÆG4 Æ"HÆ#F( Æ(GÇG4 ÇGÇG4 ÇG Ç	G-ÇG(Ç"G4 Ç(G-Ç-G4 Ç2G4 Ç4	HÇ=HÈHÈHc                  ó4   — ddl m}  | j                  d«      du S )Nr   ©rŽ   Ú%allow_public_health_readiness_detailsT©rÇ   rŽ   rÝ   r  s    rK   Ú&_allow_public_health_readiness_detailsr!  k  s   € Ý;à×ÑÐ GÓHÈDÐPÐPrM   c                  ó4   — ddl m}  | j                  d«      du S )Nr   r  Úenable_drain_endpointTr   r  s    rK   Ú_drain_endpoint_enabledr$  q  s   € Ý;à×ÑÐ 7Ó8¸DÐ@Ð@rM   c                  óŒ   — ddl m}  | j                  d«      }t        |t        «      r|r|S t        j                  d«      }|r|S y)a  
    Shared secret required on the X-Drain-Token header to call /health/drain.

    Falls back to the ``DRAIN_ENDPOINT_TOKEN`` env var when unset in
    general_settings so the kubelet preStop hook can supply it via
    ``valueFrom.secretKeyRef`` without a config reload.
    r   r  Údrain_endpoint_tokenÚDRAIN_ENDPOINT_TOKENN)rÇ   rŽ   rÝ   r=   rC   rò   ró   )rŽ   r©   Ú	env_tokens      rK   Ú_drain_endpoint_tokenr)  w  sD   € õ <à#×'Ñ'Ð(>Ó?€EÜ�%œÔ¡%ØˆÜ—y‘yÐ!7Ó8€IÙØÐØrM   c                 ó¾   — t        «       }|€y| j                  j                  d«      xs d}t        j                  ||«      st        t        j                  d¬«      ‚y)a!  
    Reject /health/drain calls that don't carry the configured X-Drain-Token.

    When no token is configured the endpoint is treated as already opted-in
    (the ``enable_drain_endpoint`` flag is the only gate). Comparison uses
    ``secrets.compare_digest`` to avoid timing leaks.
    Nzx-drain-tokenr§   z Invalid or missing X-Drain-Tokenr:   )r)  r»   rÝ   ÚsecretsÚcompare_digestr   r   ÚHTTP_401_UNAUTHORIZED)r„   ÚexpectedÚsupplieds      rK   Ú_authorize_drain_requestr0  Š  s\   € ô ,Ó-€HØÐØØ—o‘o×)Ñ)¨/Ó:Ò@¸b€HÜ×!Ñ! (¨HÔ5ÜÜ×4Ñ4Ø5ô
ð 	
ð 6rM   c              ƒ   ó°   K  — ddl m} |€yt        «       ƒ d{  –—† }|d   dk7  r)t        j                  «       st
        j                  | _        |d   S 7 Œ:­w)zà
    Return the db status string for the public probe and flip the response to
    503 when a configured DB is unreachable. Mirrors the legacy values:
    "Not connected" (no DB configured), "connected", "disconnected".
    r   r   Nr  r   rÙ  )rÇ   r�   r×  r'   r  r   rx  r;   )r   r�   r  s      rK   Ú_resolve_public_readiness_dbr2  �  sX   è ø€ õ 9àÐØä$>Ó$@×@Ðà˜Ñ" kÒ1Ü(×OÑOÔQä%×BÑBˆÔØ˜HÑ%Ð%ð Aús   ‚A™Aš;Az/health/readiness)r‚   c              ƒ   óÚ   K  — t        j                  «       rt        j                  | _        ddiS t        «       rt        | ¬«      ƒ d{  –—† S t        | ¬«      ƒ d{  –—† }d|dœS 7 Œ7 Œ­w)un  
    Public readiness probe. Returns a low-detail payload safe to expose to
    unauthenticated load balancers â€” `status` plus `db` so orchestrators and
    external probes can distinguish "healthy" from "DB unreachable" without a
    credential. Admins can opt into the legacy detailed payload with
    general_settings.allow_public_health_readiness_details.
    r   Úshutting_down©r   Nr&  )r   r  )r1   Úis_shutting_downr   rx  r;   r!  r  r2  )r   Ú	db_statuss     rK   Úhealth_readinessr8  ±  sc   è ø€ ô ×/Ñ/Ô1Ü%×BÑBˆÔØ˜/Ð*Ð*ä-Ô/Ü2¸HÔE×EÐEä9À8ÔL×L€IØ yÑ1Ð1ð FøàLús$   ‚AA+Á	A'Á
A+ÁA)Á
A+Á)A+z/health/readiness/detailsc              ƒ   ó6   K  — t        | ¬«      ƒ d{  –—† S 7 Œ­w)zN
    Authenticated readiness diagnostics with DB/cache/callback metadata.
    r5  N)r  r5  s    rK   Úhealth_readiness_detailsr:  È  s   è ø€ ô /¸ÔA×AÐAÐAús   ‚’“z/health/backlogc               ƒ   ó"   K  — dt        «       iS ­w)u`  
    Returns the number of HTTP requests currently in-flight on this uvicorn worker.

    Use this to measure per-pod queue depth. A high value means the worker is
    processing many concurrent requests â€” requests arriving now will have to wait
    for the event loop to get to them, adding latency before LiteLLM even starts
    its own timer.
    Úin_flight_requestsr/   rV   rM   rK   Úhealth_backlogr=  Ô  s   è ø€ ð !Ô"8Ó":Ð;Ð;ùs   ‚z/health/drainc              ƒ   óÜ   K  — t        «       st        t        j                  d¬«      ‚t	        | «       t        j                  «        t        j                  d¬«      ƒ d{  –—† }d|dœS 7 Œ	­w)a  
    Graceful-drain probe for Kubernetes ``preStop`` hooks.

    Disabled by default and returns 404 unless ``general_settings`` sets
    ``enable_drain_endpoint: true``. Calling it flips a process-wide
    shutting-down flag, so a successful call permanently takes the worker out
    of rotation until the pod restarts.

    Because the kubelet calls preStop hooks without proxy credentials, the
    endpoint does not require ``user_api_key_auth``. To prevent any
    pod-reachable caller from triggering shutdown, set
    ``general_settings.drain_endpoint_token`` (or the ``DRAIN_ENDPOINT_TOKEN``
    env var) and supply the same value on the ``X-Drain-Token`` header from
    the preStop hook. Calls without the header (or with a wrong value) get a
    401 and have no side effect.

    When enabled, it marks the worker as shutting down (so /health/readiness
    and /health/liveliness immediately start returning 503, removing the pod
    from service) and blocks until the in-flight request counter drains to
    zero or ``GRACEFUL_SHUTDOWN_TIMEOUT`` elapses. Unlike a fixed ``sleep``,
    this returns as soon as real in-flight work is done.

    Wire it up as:

    ```yaml
    lifecycle:
      preStop:
        httpGet:
          path: /health/drain
          port: 4000
          httpHeaders:
            - name: X-Drain-Token
              value: <same value as drain_endpoint_token>
    ```
    z	Not Foundr:   T)Úexclude_selfNÚdrained)r   Údrained_requests)r$  r   r   rk  r0  r1   Ústart_shutdownÚwait_for_drain)r„   r@  s     rK   Úhealth_drainrD  å  sZ   è ø€ ôP #Ô$Ü¬×(AÑ(AÈ+ÔVÐVÜ˜WÔ%Ü×*Ñ*Ô,Ü2×AÑAÈtÔT×T€GØ°WÑ=Ð=ð Uús   ‚AA,Á A*Á!
A,z/health/livelinessz/health/livenessc              ƒ   óf   K  — t        j                  «       rt        j                  | _        ddiS y­w)zÊ
    Unprotected endpoint for checking if worker is alive.

    Returns 503 once graceful shutdown has begun so Kubernetes stops counting
    the draining pod as live and terminates it on schedule.
    r   r4  z
I'm alive!)r1   r6  r   rx  r;   r5  s    rK   Úhealth_livelinessrF    s0   è ø€ ô ×/Ñ/Ô1Ü%×BÑBˆÔØ˜/Ð*Ð*Øùs   ‚/1c               ƒ   ó0   K  — ddddœ} t        | d¬«      S ­w)z6
    Options endpoint for health/readiness check.
    úGET, OPTIONSÚ*©ÚAllowzAccess-Control-Allow-MethodszAccess-Control-Allow-HeaderséÈ   ©r»   r;   ©r   ©Úresponse_headerss    rK   Úhealth_readiness_optionsrQ  *  s)   è ø€ ð  Ø(6Ø(+ñÐô
 Ð,¸#Ô>Ð>ùó   ‚c               ƒ   ó0   K  — ddddœ} t        | d¬«      S ­w)z7
    Options endpoint for health/liveliness check.
    rH  rI  rJ  rL  rM  rN  rO  s    rK   Úhealth_liveliness_optionsrT  :  s)   è ø€ ð  Ø(6Ø(+ñÐô
 Ð,¸#Ô>Ð>ùrR  z/health/test_connectionzXThe mode to test the model with. If not provided, auto-detected from model capabilities.zIParameters for litellm.completion, litellm.embedding for the health checkzModel info for the health checkÚmode)ÚchatrÖ   Ú	embeddingÚaudio_speechÚaudio_transcriptionÚimage_generationÚ
image_editÚvideo_generationÚbatchÚrerankÚrealtimeÚ	responsesÚocrr2  r1  c           
   ƒ   óÞ  K  — ddl m} ddlm} ddlm}m}m}	m}
 ddl	m
}m} 	 |
€#t        dd|j                  j                  i¬	«      ‚|xs i }t        |«       |rt        |«       |j!                  d
«      }i }d}|�� |xs i }|j!                  d«      }	 d}|r|j#                  |¬«      }|�9|j$                  j'                  d¬«      }|j(                  j'                  d¬«      }n·|rµ|j+                  |¬«      }|rt-        |«      dk(  rD|j+                  d¬«      }|r0|D ]+  }|j!                  di «      j!                  d
«      |k(  sŒ(|g} n |rMt-        |«      dkD  r?t/        |d   j!                  di «      «      }t/        |d   j!                  d«      xs i «      }i t7        |||j!                  d«      du ¬«      ¥|¥}|�|n|}t9        |xs i |¬«      }|j;                   |d |d!i |¤Ž|¬«      ||
|	¬«      ƒ d{  –—†  |xs |j=                  dd«      }t?        tA        jB                  ||ddg¬«      tD        «      ƒ d{  –—† }tG        i |¥|¥d¬«      }d|v rdnd|dœS # t0        $ r!}t3        j4                  d||«       Y d}~Œíd}~ww xY w7 Œ“7 ŒO# t        $ r}|‚d}~wt0        $ r;}t3        j4                  d|«       t        tH        jJ                  dd |› �i¬	«      ‚d}~ww xY w­w)"a,  
    Test a direct connection to a specific model.
    
    This endpoint allows you to verify if your proxy can successfully connect to a specific model.
    It's useful for troubleshooting model connectivity issues without going through the full proxy routing.
    
    Example:
    ```bash
    # If model is configured in proxy_config.yaml, you only need to specify the model name:
    curl -X POST 'http://localhost:4000/health/test_connection' \
      -H 'Authorization: Bearer sk-1234' \
      -H 'Content-Type: application/json' \
      -d '{
        "litellm_params": {
            "model": "gpt-4o"
        },
        "mode": "chat"
      }'
    
    # The endpoint will automatically use api_key, api_base, etc. from proxy_config.yaml
    
    # You can also override specific params or test with custom credentials:
    curl -X POST 'http://localhost:4000/health/test_connection' \
      -H 'Authorization: Bearer sk-1234' \
      -H 'Content-Type: application/json' \
      -d '{
        "litellm_params": {
            "model": "azure/gpt-4o",
            "api_key": "os.environ/AZURE_OPENAI_API_KEY",
            "api_base": "os.environ/AZURE_OPENAI_ENDPOINT",
            "api_version": "2024-10-21"
        },
        "mode": "chat"
      }'
    ```
    
    Note: 
    - If the model is configured in proxy_config.yaml, credentials (api_key, api_base, etc.) 
      will be automatically loaded from the config (with resolved environment variables).
    - You can override specific params by including them in the request.
    - You can use `os.environ/VARIABLE_NAME` syntax to reference environment variables,
      which will be resolved automatically (same as in proxy_config.yaml).
    
    Returns:
        dict: A dictionary containing the health check result with either success information or error details.
    r   )ÚCommonProxyErrors)ÚModelManagementAuthChecks)rŽ   rm  r¾  r�   )Ú
DeploymentÚLiteLLM_ParamsNr½   r9   r:   r˜   r?   re  T)Úexclude_none)r  r2  r1  zKCould not find model %s in router: %s. Proceeding with request params only.rR   )rR   )r1  r2  Ú
test_model)r  r2  r1  )Úmodel_paramsr‹   r�   r¾  rU  ztest from litellm)ri  rU  ÚpromptÚinput)r  r›   )r   r?  zOlitellm.proxy.health_endpoints.test_model_connection(): Exception occurred - %szFailed to test connection: rV   )&Úlitellm.proxy._typesrc  Ú=litellm.proxy.management_endpoints.model_management_endpointsrd  rÇ   rŽ   rm  r¾  r�   Úlitellm.types.routerre  rf  r   Údb_not_connected_errorrJ   rL   rÝ   rl  r2  Ú
model_dumpr1  Úget_model_listr*  r>   rõ   r   rö   r]   r+   Úcan_user_make_model_callr@   r.   rÉ   Úahealth_checkr   r*   r   rú   )r„   rU  r2  r1  r‹   rc  rd  rŽ   rm  r¾  r�   re  rf  Úrequest_litellm_paramsr  Úconfig_litellm_paramsÚloaded_model_infoÚrequest_model_infoÚrequest_model_idÚdeployment_by_idÚdeploymentsÚall_deploymentsrn  r  Úresolved_model_infor?  Úcleaned_results                              rK   Útest_model_connectionr~  N  s”  è ø€ õd 7õ÷ó ÷ @ðy
ØÐ ÜØØÐ!2×!IÑ!I×!OÑ!OÐPôð ð )7Ò(<¸"Ðô 	&Ð&<Ô=ÙÜ)¨*Ô5Ø2×6Ñ6°wÓ?ˆ
ð ')ÐØ)-ÐØÑ!ð )3Ò(8°bÐØ&8×&<Ñ&<¸TÓ&BÐð!Ø#'Ð Ù#Ø'1×'@Ñ'@ÐJZÐ'@Ó'[Ð$à#Ð/Ø,<×,KÑ,K×,VÑ,VÐdhÐ,VÓ,iÐ)Ø(8×(CÑ(C×(NÑ(NÐ\`Ð(NÓ(aÑ%Ùð #-×";Ñ";ÀzÐ";Ó"R�Kñ '¬#¨kÓ*:¸aÒ*?Ø1;×1JÑ1JÐVZÐ1JÓ1[˜Ù*Ø.=ò * 
Ø#-§>¡>Ð2BÀBÓ#G×#KÑ#KÈGÓ#TÐXbÓ#bØ3=°, KÙ$)ð*ñ
 #¤s¨;Ó'7¸!Ò';ô 15°[À±^×5GÑ5GÐHXÐZ\Ó5]Ó0^Ð-Ü,0°¸Q±×1CÑ1CÀLÓ1QÒ1WÐUWÓ,XÐ)ð
Ü+Ø%Ø&Ø.>×.BÑ.BÐCbÓ.cÐgkÐ.kôð
ð %ð
ˆð ;LÐ:WÑ%6Ð]gÐÜ@Ø*Ò0¨bØ)ô
ˆð (×@Ñ@Ù#Ø'Ù-Ñ?°Ñ?Ø.ôð
 0Ø'Ø%ð Aó 	
÷ 		
ð 		
ð Ò7�~×)Ñ)¨&°$Ó7ˆä.Ü×!Ñ!Ø+ØØ*Ø*Ð+ô	ô )ó
÷ 
ˆô !5Ð5Q¸Ð5QÈ&Ð5QÐ[_Ô `ˆð ")¨FÑ!2‘g¸	Ø$ñ
ð 	
øô_ ò Ü$×*Ñ*ØaÐcmÐop÷ñ ûðúð,		
øð
ùô$ ò ØˆûÜò 
Ü×"Ñ"Ð#tÐvwÔxÜÜ×=Ñ=ØÐ:¸1¸#Ð>Ð?ô
ð 	
ûð
üs‡   ‚!K-¤A2J ÂB2I' Å
AI' ÆA!J È JÈAJ ÉJÉJ É&K-É'	JÉ0JÊJ ÊJÊJ ÊJ Ê	K*Ê!J#Ê#K*Ê/6K%Ë%K*Ë*K-)FrU   )NN)—rç   r~  rï   r  rò   r+  r+  r÷   Úcollections.abcr   r   r   r   Útypingr   r   r	   r
   r   rª  r   r   r   r   r   r   Útyping_extensionsr   rÉ   Úlitellm._loggingr   r   Úlitellm.constantsr   Ú+litellm.integrations.SlackAlerting.ms_teamsr   r   r   Ú1litellm.litellm_core_utils.custom_logger_registryr   Ú&litellm.llms.custom_httpx.http_handlerr   rl  r   r   r   r   r   r    r!   r"   r#   r$   rˆ   r%   Ú$litellm.proxy.auth.user_api_key_authr&   Ú"litellm.proxy.db.exception_handlerr'   Ú'litellm.proxy.db.proxy_worker_heartbeatr(   Úlitellm.proxy.health_checkr)   r*   r+   r,   r-   r.   Ú6litellm.proxy.middleware.in_flight_requests_middlewarer0   Ú0litellm.proxy.shutdown.graceful_shutdown_managerr1   Ú2litellm.router_utils.clientside_credential_handlerr2   r3   Úlitellm.secret_managers.mainr4   r>   rL   Ú	frozensetrO   rC   r}   Úobjectr}  r]   re   rf   rÈ   rx   r   rÝ   r‰   ÚQueryr  r  r!  rB   Úfloatr.  r5  r9  rE  rI  ÚPROXY_ADMINrJ   ÚPROXY_ADMIN_VIEW_ONLYrJ  r×   rV  rO  r\  ra  ri  ro  rŽ  Úintr›  r   r­  r¸  r¼  rÇ  rÉ  rë   rÍ  rÎ  rÏ  r×  rÕ  rú  r_   rþ  r  r  r!  r$  r)  r0  r2  r8  r:  r=  rD  rF  ÚoptionsrQ  rT  rî   ÚBodyr~  rV   rM   rK   ú<module>r˜     s.
  ðÜ Û Û Û Û 	Û Û Û ß -ß (ß 7Õ 7ã ß P× PÝ &ã ß AÝ :÷ñ õ
 SÝ C÷÷ ÷ õõ CÝ GÝ L÷÷ õõ U÷õ 9ð
$¨$ð $°4ó $ñB 4=ðØ	7ðà	#ðð 	"ñó4Ð ˜5 ¨3¡Ñ0ó ð +0ñhØ˜3 ˜;Ñ'ðhà˜C ˜KÑ(ðhð $(ðhð 
ˆ#ˆvˆ+Ñó	hò<#ñ: “€ˆÓ àð	ñð$ 
ñ%
ð 	ô.˜iô ô )ô ð
 ‡�ØØ
ˆÙÐ+Ó,Ð-ð ó ð
1 ò 1óð
1ð& ‡�ØØ
ˆÙÐ+Ó,Ð-ð ó ñ )0Ð0AÓ(BØ%˜Ÿ™Ð2RÔSñy
Ø%ðy
àòy
óð
y
ðx	¨Dó ò$	ð&  ñwàðwð ðwð ð	wð
 ðwð �4‰Zðwð �D‰jówðD°4ð ¸Dó ð@8Øð8àð8ð ð8ð 
ó	8ð@ "ñ9àð9ð ð9ð ð	9ð
 �d‘
ó9ðD "ñ1jàð1jð ð1jð ð	1jð
 ð1jð �d‘
ó1jñj &à×$Ñ$×*Ñ*ð
 	×.Ñ.×4Ñ4ðó	Ð �Eó 	ð, ~ð ,¸$ó ,ð¸ð Àó ð""¨Dð "¸¸t¹ð "ÈsÐUYÉzð "Ð^aÐdhÑ^hó "ðJ°tð ÐPSð ÐX\ó ðB Øó-ð`!Ø�‰:ð!à�D‰jð!ð 	ˆ4�Zó	!ð: ‡�ˆI˜X˜J±gÐ>OÓ6PÐ5Q€ÓRñ )0Ð0AÓ(BØ%˜Ÿ™ dÐ8[Ô\Ø(˜7Ÿ=™=¨Ð;\Ô]ñ	pØðpà%ðpð �‰:ðpð �D‰jò	pó Sðpðf ‡�Ð X J¹gÐFWÓ>XÐ=Y€ÓZá(/Ð0AÓ(BØ%˜Ÿ™ dÐ8WÔXØ - §¡¨dÐ@fÔ gØ�—‘˜sÐ0MÐRSÐX\Ô]Ø�'—-‘- Ð/JÈqÔQñ$
Ø%ð$
à�‰:ð$
ð ˜‘:ð$
ð ð	$
ð
 ò$
ó [ð$
ðN ‡�Ð H :¹WÐEVÓ=WÐ<X€ÓYá(/Ð0AÓ(Bñ
Ø%ò
ó Zð
ð> ‡�Ð#¨8¨*ÁGÐL]ÓD^ÐC_€Ó`á(/Ð0AÓ(Bñ'
Ø%ò'
ó að'
ðT.˜D  c ™N¨TÑ1ó .ð2"¨¨c°3¨h©ð "¸Dó "ð ‡�ØØ
ˆÙÐ+Ó,Ð-ð ó ñ )0Ð0AÓ(Bñ#Ø%ò#óð
#ôL�Iô ð
 -6À|ÀxÇ|Á|Ã~Ñ!V€�Ó Vð -0Ð " EÓ /ð .1Ð # UÓ 0ð[¨-ó [ð'°Mó 'ðT ‡�ØØ
ˆÙÐ+Ó,Ð-ð ó ð
 ‡�ØØ
ˆÙÐ+Ó,Ð-ð ó ñ
BóóðBòJ
!ð +MÐ   %Ó Lð> dó >ð: !%ñRPØ˜‰oðRPà	ˆ#ˆsˆ(�^óRPðjQ°ó QðA ó Að˜s T™zó ð&
 gð 
°$ó 
ð&&°ð &¸có &ð( ‡�ØØ
ˆð ó ð2 Xò 2ó	ð2ð& ‡�ØØ
ˆÙÐ+Ó,Ð-ð ó ð
B¨Xò Bóð
Bð ‡�ØØ
ˆÙÐ+Ó,Ð-ð ó ñ
	<óð
	<ð ‡�ØØ
ˆð ó ð)> ò )>ó	ð)>ðX ‡�ØØ
ˆð ó ð ‡�ØØ
ˆð ó ð
 hò 
ó	ó	ð
ð ‡‚ØØ
ˆð ó ñ	?ó	ð	?ð ‡‚ØØ
ˆð ó ð ‡‚ØØ
ˆð ó ñ	?ó	ó	ð	?ð ‡‚ØØ
ˆÙÐ+Ó,Ð-ð ó ð, ˆW�\Š\ØØnôð (˜7Ÿ<š<ØØ_ôð $�w—|’|ØØ5ôñ )0Ð0AÓ(Bñ;R
ØðR
à
ð	ñð ñðR
ð* ð+R
ð2 ð3R
ð: &ò;R
óñ
R
rM   