Ë
    tPêj€"  ã                   ó$  — U d 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
 ddlmZ ddlmZ ddlmZmZ dd	lmZ dd
lmZmZmZmZ  eddg¬«      Zeed<    G d„ d«      Zej;                  d e	e«      g¬«       e	e«      fdededefd„«       Zy)uJ  
Ingest pre-built logging payloads from external producers and replay them
through LiteLLM's standard success/failure callback fan-out.

This exists for hosts that own a request outside the Python process â€” e.g. the
`litellm-rust` gateway proxying realtime websockets. Those hosts can't use the
in-process logging object, so they POST a finished `StandardLoggingPayload` here
and Python replays it through the exact same path a normal completion uses:
`Logging.async_success_handler` / `async_failure_handler`. Every registered
callback (spend logs, Langfuse, Datadog, ...) fires unchanged â€” there is no
spend-logs-specific or callback-specific code here, only the replay.

The endpoint is generic: realtime is the first producer, but the contract is the
self-describing `StandardLoggingPayload`, so completions/responses can use it too.
é    N)ÚdatetimeÚtimezone)ÚAnyÚFinal)Ú	APIRouterÚDependsÚHTTPException)Úverbose_proxy_logger)ÚLogging)ÚLitellmUserRolesÚUserAPIKeyAuth)Úuser_api_key_auth)ÚCallbackLogFailureÚCallbackLogRecordÚCallbackLogsRequestÚCallbackLogsResponsez/v1/rust_control_planezrust control plane)ÚprefixÚtagsÚrust_control_plane_routerc                   ó¢   — e Zd ZdZededefd„«       Zedee	ef   de
fd„«       Zedee	ef   dee	ef   fd„«       Zdedd	fd
„Zdee   defd„Zy	)ÚCallbackLogsReplayeru~  
    Replays finished logging payloads through LiteLLM's callback fan-out.

    Each helper is small and pure so the replay path is easy to read and test:
    rebuild a `Logging` object from the payload, seed `model_call_details` with
    exactly what the callbacks read, then dispatch to the success/failure
    handler. No spend/callback logic lives here â€” only the replay.
    ÚvalueÚreturnc                 óö   — t        | t        t        f«      r.t        j                  t        | «      t
        j                  ¬«      S t        | t        «      r| S t        j                  t
        j                  ¬«      S )zI`StandardLoggingPayload` stores startTime/endTime as float epoch seconds.)Útz)Ú
isinstanceÚintÚfloatr   Úfromtimestampr   ÚutcÚnow)r   s    ú|/home/oem/CyberBrain26-unified/.venv/lib/python3.12/site-packages/litellm/proxy/logging_endpoints/callback_logs_endpoints.pyÚ_epoch_to_datetimez'CallbackLogsReplayer._epoch_to_datetime2   sO   € ô �eœc¤5˜\Ô*Ü×)Ñ)¬%°«,¼8¿<¹<ÔHÐHÜ�eœXÔ&ØˆLÜ�|‰|œxŸ|™|Ô,Ð,ó    Úpayloadc                 ó6  — | j                  d«      xs d}| j                  d«      xs d}t        j                  | j                  d«      «      }| j                  d«      xs0 | j                  d«      xs t        t	        j
                  «       «      }t        || j                  d«      xs g d	|||d¬
«      }| j                  d«      xs i }|j                  d«      |j                  d«      |j                  d«      |j                  d«      |j                  d«      |j                  d«      |j                  d«      dœ}|j                  j                  ||| j                  d«      | j                  d«      xs d| d|i| j                  d«      xs d	dœ«       |S )a�  
        Reconstruct a `Logging` object from a finished payload and seed
        `model_call_details` with exactly what the success/failure callbacks
        read: the prebuilt `standard_logging_object`, the resolved
        `response_cost`, and the `litellm_params.metadata` keys used for cost
        attribution. Setting `standard_logging_object` up front makes the handler
        skip rebuilding it.
        ÚmodelÚ Ú	call_typeÚacompletionÚ	startTimeÚlitellm_call_idÚidÚmessagesF)r'   r.   Ústreamr)   Ú
start_timer,   Úfunction_idÚmetadataÚuser_api_key_hashÚuser_api_key_aliasÚuser_api_key_user_idÚuser_api_key_team_idÚuser_api_key_org_idÚuser_api_key_end_user_idÚspend_logs_metadata)Úuser_api_keyr4   r5   r6   r7   r8   r9   Úcustom_llm_providerÚresponse_costg        Ú	cache_hit)r'   r)   r;   r<   Ústandard_logging_objectÚlitellm_paramsr=   )	Úgetr   r#   ÚstrÚuuidÚuuid4ÚLiteLLMLoggingÚmodel_call_detailsÚupdate)r%   r'   r)   r0   Úcall_idÚlogging_objr2   Úlitellm_metadatas           r"   Ú_build_logging_objz'CallbackLogsReplayer._build_logging_obj;   s�  € ð —{‘{ 7Ó+Ò1¨rˆØ"Ÿ;™; {Ó3ÒD°}ˆ	Ü0×CÑCÀGÇKÁKÐP[ÓD\Ó]ˆ
Ø Ÿ™Ð%6Ó7Òa¸7¿;¹;ÀtÓ;LÒaÔPSÔTX×T^ÑT^ÓT`ÓPaˆä+ØØ—[‘[ Ó,Ò2°ð ØØ!Ø#Øô
ˆð  +2¯+©+°jÓ*AÒ*GÀRˆà$ŸL™LÐ)<Ó=Ø"*§,¡,Ð/CÓ"DØ$,§L¡LÐ1GÓ$HØ$,§L¡LÐ1GÓ$HØ#+§<¡<Ð0EÓ#FØ(0¯©Ð5OÓ(PØ#+§<¡<Ð0EÓ#Fñ3
Ðð 	×&Ñ&×-Ñ-àØ&Ø'.§{¡{Ð3HÓ'IØ!(§¡¨_Ó!=Ò!DÀØ+2Ø#-Ð/?Ð"@Ø$Ÿ[™[¨Ó5Ò>¸ñô
	
ð Ðr$   c                 ó’   — | j                  d«      | j                  dd«      | j                  dd«      | j                  dd«      dœdœS )zBMinimal response object so usage-derived spend-log fields resolve.r-   Úprompt_tokensr   Úcompletion_tokensÚtotal_tokens)rL   rM   rN   )r-   Úusage)r@   )r%   s    r"   Ú_response_obj_from_payloadz/CallbackLogsReplayer._response_obj_from_payloadr   sJ   € ð —+‘+˜dÓ#à!(§¡¨_¸aÓ!@Ø%,§[¡[Ð1DÀaÓ%HØ '§¡¨N¸AÓ >ññ
ð 	
r$   ÚrecordNc           	   ƒ   óv  K  — |j                   }t        j                  d|j                  |j	                  d«      |j	                  d«      |j	                  d«      «       | j                  |«      }| j                  |j	                  d«      «      }| j                  |j	                  d«      «      }|j                  dk(  r,|j                  | j                  |«      ||¬«      ƒ d	{  –—†  y	|j                  xs |j	                  d
«      xs d}|j                  t        |«      d||¬«      ƒ d	{  –—†  y	7 ŒO7 Œ­w)z?Replay one record through the matching success/failure handler.zECallbackLogsReplayer: replaying %s record id=%s model=%s call_type=%sr-   r'   r)   r+   ÚendTimeÚsuccess)Úresultr0   Úend_timeNÚ	error_strzreplayed failurer(   )Útraceback_exceptionr0   rV   )Ústandard_logging_payloadr
   ÚdebugÚstatusr@   rJ   r#   Úasync_success_handlerrP   ÚerrorÚasync_failure_handlerÚ	Exception)ÚselfrQ   r%   rH   r0   rV   rW   s          r"   ÚreplayzCallbackLogsReplayer.replay~   s&  è ø€ à×8Ñ8ˆÜ×"Ñ"ØSØ�M‰MØ�K‰K˜ÓØ�K‰K˜Ó Ø�K‰K˜Ó$ô	
ð "×4Ñ4°WÓ=ˆØ ×3Ñ3°G·K±KÀÓ4LÓMˆ
Ø×1Ñ1°'·+±+¸iÓ2HÓIˆà�=‰=˜IÒ%Ø×3Ñ3Ø×6Ñ6°wÓ?Ø%Ø!ð 4ó ÷ ñ ð  &Ÿ|™|Ò]¨w¯{©{¸;Ó/GÒ]ÐK]ˆIØ×3Ñ3Ü˜)Ó$Ø$&Ø%Ø!ð	 4ó ÷ ñ ðøðús%   ‚C#D9Ã%D5Ã&A	D9Ä/D7Ä0D9Ä7D9Úrecordsc           
   ƒ   óž  K  — d}g }t        |«      D ]$  \  }}	 | j                  |«      ƒ d{  –—†  |dz  }Œ& t        j                  d|t        |«      «       t        |t        |«      |¬«      S 7 ŒB# t        $ rO}|j                  t	        |t        |«      ¬«      «       t        j                  d|t        |«      «       Y d}~Œ³d}~ww xY w­w)z—Replay a batch; a single bad record never sinks the rest. Each failure
        is reported back with its batch index so the caller can retry/triage it.r   Né   )Úindexr]   z4CallbackLogsReplayer: failed to replay record %s: %sz7CallbackLogsReplayer: batch done processed=%s failed=%s)Ú	processedÚfailedÚfailures)Ú	enumeratera   r_   Úappendr   rA   r
   Ú	exceptionrZ   Úlenr   )r`   rb   rf   rh   re   rQ   Úes          r"   Úreplay_batchz!CallbackLogsReplayer.replay_batchœ   sÉ   è ø€ ð ˆ	Ø46ˆÜ& wÓ/ò 
	‰MˆE�6ð	Ø—k‘k &Ó)×)Ð)Ø˜Q‘‘	ð
	ô 	×"Ñ"ØEØÜ�‹Mô	
ô
 $¨iÄÀHÃÐX`ÔaÐað *ùäò Ø—‘Ô 2¸ÄcÈ!ÃfÔ MÔNÜ$×.Ñ.ØJØÜ˜“F÷ñ ûðüs>   ‚C™A2­A0®	A2·9CÁ0A2Á2	C
Á;ACÃ CÃC
Ã
C)Ú__name__Ú
__module__Ú__qualname__Ú__doc__Ústaticmethodr   r   r#   ÚdictrA   rD   rJ   rP   r   ra   Úlistr   rn   © r$   r"   r   r   (   s·   „ ñð ð- #ð -¨(ò -ó ð-ð ð4 D¨¨c¨¡Nð 4°~ò 4ó ð4ðl ð	
¨D°°c°©Nð 	
¸tÀCÈÀH¹~ò 	
ó ð	
ðÐ#4ð ¸ó ð<b¨$Ð/@Ñ*Að bÐFZô br$   r   z/logs)ÚdependenciesÚbodyÚuser_api_key_dictr   c              ƒ   ó¸   K  — |j                   t        j                  k7  rt        dd¬«      ‚t	        «       j                  | j                  «      ƒ d{  –—† S 7 Œ­w)zÝ
    Replay a batch of finished logging payloads through the callback fan-out.

    Admin-only: the payloads write spend logs and trigger every callback, so this
    is a trusted internal route, not a public surface.
    i“  zE/v1/rust_control_plane/logs is admin-only (proxy admin key required).)Ústatus_codeÚdetailN)Ú	user_roler   ÚPROXY_ADMINr	   r   rn   rb   )rx   ry   s     r"   Úingest_callback_logsr   ´   sP   è ø€ ð ×"Ñ"Ô&6×&BÑ&BÒBÜØØZô
ð 	
ô
 &Ó'×4Ñ4°T·\±\ÓB×BÐBÐBús   ‚AAÁAÁA)rr   rB   r   r   Útypingr   r   Úfastapir   r   r	   Úlitellm._loggingr
   Ú*litellm.litellm_core_utils.litellm_loggingr   rD   Úlitellm.proxy._typesr   r   Ú$litellm.proxy.auth.user_api_key_authr   Ú+litellm.types.proxy.callback_logs_endpointsr   r   r   r   r   Ú__annotations__r   Úpostr   rv   r$   r"   ú<module>r‰      s¶   ðòó  ß 'ß ç 5Ñ 5å 1Ý Pß AÝ B÷ó ñ $-Ð4LÐThÐSiÔ#jÐ ˜5Ó j÷Ibñ IbðX ×ÑØÙÐ+Ó,Ð-ð  ó ñ )0Ð0AÓ(BñCØ
ðCà%ðCð òCó	ñCr$   