Ë
    tPêjžÒ  ã            	      ó^  — U d dl m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 d dlmZ d dlmZmZmZmZ d dlmZmZ d dlZd d	lmZ d d
l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$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/m0Z0 d dl1m2Z2m3Z3 d dl4m5Z5 d dl6m7Z7 e G d„ d«      «       Z8ejr                  jt                  ejv                  jt                  ejx                  jt                  ejz                  jt                  ej|                  jt                  ej~                  jt                  ej€                  jt                  ej‚                  jt                  dœZBdeCd<    G d„ deD«      ZEdXd„ZFdYd„ZGdZd„ZH	 	 	 	 	 	 	 	 	 	 	 	 	 	 d[d„ZI	 	 	 	 d\	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 d]d„ZJ	 d^	 	 	 	 	 	 	 d_d „ZKd`d!„ZL	 	 	 	 d`d"„ZM	 	 	 	 d`d#„ZN	 	 	 da	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 dbd$„ZO	 	 	 	 	 	 	 	 dcd%„ZP	 	 	 	 	 	 	 	 	 	 ddd&„ZQ	 	 	 	 	 	 	 	 ded'„ZRdfd(„ZSdgd)„ZT	 	 	 	 	 	 	 	 	 	 dhd*„ZU	 	 	 	 	 	 	 	 did+„ZV	 	 	 	 	 	 	 	 	 	 	 	 djd,„ZWdkd-„ZX	 	 	 	 	 	 dld.„ZYdmd/„ZZ	 d^	 	 	 	 	 	 	 	 	 dnd0„Z[	 d^	 	 	 	 	 	 	 	 	 dod1„Z\	 	 	 	 	 	 dpd2„Z]	 	 	 	 	 	 dqd3„Z^	 	 	 	 	 	 	 	 drd4„Z_	 	 	 	 	 	 dsd5„Z`dtd6„Zadud7„Zbdvd8„Zc	 dw	 	 	 	 	 	 	 	 	 dxd9„Zd	 dw	 	 	 	 	 	 	 	 	 dxd:„Ze	 dw	 	 	 	 	 	 	 	 	 	 	 dyd;„Zf	 dw	 	 	 	 	 	 	 	 	 	 	 dzd<„Zg	 dw	 	 	 	 	 	 	 	 	 	 	 dyd=„Zh	 dw	 	 	 	 	 	 	 	 	 	 	 dzd>„Zi	 	 	 	 	 	 d{d?„Zj	 	 	 	 	 	 d|d@„Zk	 	 	 	 	 	 d}dA„Zl	 	 	 	 	 	 d~dB„Zm	 	 	 	 	 	 ddC„Zn	 	 	 	 	 	 	 	 d€dD„ZodEZpdFeCdG<   	 	 	 	 	 	 	 	 d�dH„Zq	 	 	 	 	 	 d‚dI„ZrdJZsdFeCdK<   dƒdL„Ztd„dM„Zu	 dw	 	 	 	 	 	 	 	 	 	 	 d…dN„ZvdOZwdFeCdP<   	 	 	 	 	 	 	 	 d†dQ„Zxd‡dR„ZydˆdS„Zzd‰dT„Z{dŠdU„Z|d‹dV„Z}dŒdW„Z~y)�é    )ÚannotationsN)ÚMappingÚSequence)Ú	dataclass)ÚdatetimeÚ	timedeltaÚtimezone)ÚMappingProxyType)ÚAnyÚFinalÚNoReturnÚcast)ÚHTTPExceptionÚstatus)Úverbose_proxy_logger)Úduration_in_seconds)Úselect_tier_for_inputÚ	tier_rate)ÚLitellm_EntityTypeÚLiteLLM_TeamMembershipÚLiteLLM_TeamTableÚLiteLLM_UserTableÚUserAPIKeyAuth)Úget_model_from_request)Úshould_throttle_budget_exceeded)ÚRouteChecks)ÚUserApiKeyCacheÚend_user_cache_keyÚmodel_access_group_cache_keyÚ$model_access_group_spend_counter_keyÚtag_cache_keyÚ%team_membership_reservation_cache_key)ÚPrismaClientÚProxyLogging)ÚRouter)ÚModelAccessGroupBudgetc                  óx   — e Zd ZU ded<   ded<   ded<   ded<   ded<   dZd	ed
<   dZd	ed<   dZd	ed<   dZded<   y)Ú_BudgetCounterÚstrÚcounter_keyÚfloatÚ
max_budgetÚfallback_spendÚentity_typeÚ	entity_idNú
str | NoneÚsource_cache_keyÚspend_log_entity_idÚwindow_durationúdatetime | NoneÚwindow_start)Ú__name__Ú
__module__Ú__qualname__Ú__annotations__r1   r2   r3   r5   © ó    út/home/oem/CyberBrain26-unified/.venv/lib/python3.12/site-packages/litellm/proxy/spend_tracking/budget_reservation.pyr(   r(   (   sI   … àÓØÓØÓØÓØƒNØ#'Ð�jÓ'Ø&*Ð˜Ó*Ø"&€O�ZÓ&Ø$(€L�/Ô(r;   r(   )ÚKeyÚTeamÚ
TeamMemberÚUserÚEndUserÚTagúModel access groupÚOrganizationzFinal[Mapping[str, str]]Ú_COUNTER_ENTITY_TYPESc                  ó0   ‡ — e Zd Z	 	 d	 	 	 	 	 dˆ fd„Zˆ xZS )Ú_CounterReservationUnavailablec                ó@   •— || _         || _        t        ‰| �  d«       y )NzCounter reservation unavailable)Útouched_counterÚcounter_invalidatedÚsuperÚ__init__)ÚselfrI   rJ   Ú	__class__s      €r<   rL   z'_CounterReservationUnavailable.__init__B   s#   ø€ ð
  /ˆÔØ#6ˆÔ Ü‰ÑÐ:Õ;r;   )FF)rI   ÚboolrJ   rO   ÚreturnÚNone)r6   r7   r8   rL   Ú__classcell__)rN   s   @r<   rG   rG   A   s1   ø„ ð !&Ø$)ð<àð<ð "ð<ð 
÷	<ñ <r;   rG   c                ód   — t        j                  d| «       t        t        j                  d¬«      ‚)Nud   fail_closed_budget_enforcement: rejecting request â€” budget reservation for %s could not be writtenzíBudget enforcement unavailable: the budget reservation could not be written to the spend counter backend, and fail_closed_budget_enforcement is enabled, so the request was rejected to avoid exceeding the configured budget. Retry shortly.)Ústatus_codeÚdetail)r   Úwarningr   r   ÚHTTP_503_SERVICE_UNAVAILABLE©r*   s    r<   Ú_raise_reservation_unavailablerY   L   s4   € Ü× Ñ ØnØôô Ü×7Ñ7ðPôð r;   c                óº   — | s
t        «       S | j                  d«      xs g }|D �ch c]*  }t        |t        «      sŒ|j                  d«      €Œ&|d   ’Œ, c}S c c}w )NÚentriesr*   )ÚsetÚgetÚ
isinstanceÚdict)Úbudget_reservationr[   Úentrys      r<   Úget_reserved_counter_keysrb   \   s^   € ÙÜ‹uˆØ'×+Ñ+¨IÓ6Ò<¸"€Gà*1öØ!&´ZÀÄtÕ5LÐQV×QZÑQZÐ[hÓQiÑQuˆˆmÓòð ùò s   ¦A¼AÁAc                óF   — |€y| d|j                   › �k(  xr t        |«      S )a›  
    Whether an over-budget key's own ``max_budget`` reservation should be
    released rather than blocked, because the key opted into throttling: the
    rate limiter slows it instead. Only the key's own ``max_budget`` counter is
    exempt; team/user/window counters still enforce normally, and under-budget
    requests never reach this branch so their concurrent-overspend protection is
    untouched.
    Fú
spend:key:)Útokenr   )r*   Úvalid_tokens     r<   Ú,_key_reservation_should_release_for_throttlerg   e   s2   € ð ÐØØ˜J {×'8Ñ'8Ð&9Ð:Ñ:ÒkÔ?^Ð_jÓ?kÐkr;   c              ƒ  óô  K  — t        | j                  |«      r)t        |g|¬«      ƒ d{  –—†  |j                  |«       |S | j                  ||z
  z
  }|dkD  rt        |||¬«      ƒ d{  –—†  |S t        j                  || j                  d| j                  › d| j                  › d|› d| j                  › �t        j                  | j                  «      | j                  xs | j                  ¬	«      ‚7 ŒÉ7 Œ‹­w)
a†  
    Decide what to do when a counter is over budget, and return the reservation
    cost to carry into the next counter. Three outcomes: an over-budget key that
    opted into throttling releases its own reservation (the rate limiter slows
    it) and keeps the cost; a partially-remaining budget resizes the reservation
    down to what is left; anything else hard-blocks by raising.
    ©r[   Údefault_reserved_costNgê-�™—q=)r[   Úcurrent_reserved_costÚnew_reserved_costzBudget has been exceeded! ú=z Current cost: z, Max budget: )Úcurrent_costr,   Úmessager.   r/   )rg   r*   Ú$_release_applied_entries_best_effortÚremover,   Ú_resize_applied_reservationÚlitellmÚBudgetExceededErrorr.   r/   rE   r]   r2   )Úcounterrf   ra   Úapplied_entriesÚreservation_costÚcurrent_spendÚremaining_before_reservations          r<   Ú%_apply_over_budget_reservation_policyrz   s   s  è ø€ ô 4°G×4GÑ4GÈÔUÜ2¸E¸7ÐZjÔk×kÐkØ×Ñ˜uÔ%ØÐà*1×*<Ñ*<ÀÐP`Ñ@`Ñ*aÐ Ø# eÒ+Ü)Ø#Ø"2Ø:ô
÷ 	
ð 	
ð
 ,Ð+ä
×
%Ñ
%Ø"Ø×%Ñ%à(Ø×"Ñ"Ð# 1 W×%6Ñ%6Ð$7ð 8Ø*˜Oð ,Ø"×-Ñ-Ð.ð0ô
 *×-Ñ-¨g×.AÑ.AÓBØ×-Ñ-ÒB°×1BÑ1Bôð ð 	løð	
ús"   ‚(C8ªC4«?C8Á*C6Á+B
C8Ã6C8c              ƒ  óä  K  — |�t        j                  |¬«      sy |dv ry t        | ||¬«      €y t        | |||||||	|
|¬«
      ƒ d {  –—† }|sy t	        | ||¬«      ƒ d {  –—† }i }t        | |||¬«      }|�|dk  ry g }	 |D ]š  }t        ||¬«      }|j                  |«       	 t        ||¬	«      ƒ d {  –—† }|�|}n6|j!                  |j                  «      }|€t#        |¬«      ƒ d {  –—† }||z   }||j$                  kD  sŒ‚t'        ||||||¬«      ƒ d {  –—† }Œœ 	 |sy t+        | |||¬«      }||dt-        t/        |xs d«      |«      dœS 7 �Œ
7 Œó7 Œ # t        $ rc}|j                  r#|j                  st        |g|¬
«      ƒ d {  –—†7   |j                  |«       |rt        |j                  ¬«       Y d }~�Œ<d }~ww xY w7 ŒÛ7 Œ¯# t(        $ r t        ||¬
«      ƒ d {  –—†7   ‚ w xY w­w)N©Úroute>   ú/modelsú
/v1/modelsú/utils/token_counter©Ú
llm_router)
Úrequest_bodyrf   Úteam_objectÚuser_objectÚprisma_clientÚuser_api_key_cacheÚproxy_logging_objÚend_user_idÚend_user_objectÚapply_user_budget_to_team_keys©rƒ   r}   r‚   )rƒ   r}   r‚   Úinput_token_countsr   ©ru   Úreserved_cost)ru   rw   ri   rX   )ru   )ru   rf   ra   rv   rw   rx   Fç        )r�   r[   Ú	finalizedÚ
input_cost)r   Úis_llm_api_router   Ú_get_budget_countersÚcount_request_input_tokensÚestimate_request_max_costÚ_counter_to_reservation_entryÚappendÚ_reserve_counterrG   rI   rJ   rp   rq   rY   r*   r]   Ú_get_current_counter_valuer,   rz   Ú	ExceptionÚestimate_request_input_costÚminr+   )rƒ   r}   r‚   rf   r„   r…   r†   r‡   rˆ   r‰   rŠ   r‹   Úfail_closed_budget_enforcementÚcountersr�   Úcurrent_spend_by_counter_keyrw   rv   ru   ra   Úreserved_valueÚexcrx   Úcached_spendr’   s                            r<   Úreserve_budget_for_requestr¤   ž   s{  è ø€ ð Ð¤+×">Ñ">ÀUÕ"KØØÐAÑAØÜ˜l¨E¸jÔIÐQØä0Ø!ØØØØ#Ø-Ø+ØØ'Ø'Eô÷ €Hñ Øä&@Ø!ØØô'÷ !Ðð =?Ð Ü0Ø!ØØØ-ô	Ðð ÐÐ#3°qÒ#8Øà;=€Oð-Øò &	ˆGÜ1ØØ.ôˆEð ×"Ñ" 5Ô)ðÜ'7Ø#Ø%5ô(÷ "�ð Ð)Ø .‘à;×?Ñ?À×@SÑ@SÓT�ØÐ'Ü)CÈGÔ)T×#T�LØ ,Ð/?Ñ ?�Ø˜w×1Ñ1Ó1Ü)NØ#Ø +ØØ$3Ø%5Ø"/ô*÷ $Ð ð ñM&	ñ\ Øä3Ø!ØØØ-ô	€Jð *Ø"ØÜœ% 
Ò 1¨cÓ2Ð4DÓEñ	ð ðwùð!øð8"ùô 2ò 	Ø×&Ò&¨s×/FÒ/FÜ>Ø!& Ø.>ô÷ ñ ð  ×&Ñ& uÔ-Ù1Ü2¸w×?RÑ?RÕSÝûð	úð  $Uøð$ùô ò Ü2Ø#Ø"2ô
÷ 	
ñ 	
ð 	ðüs´   ‚AG0ÁEÁ	G0Á!EÁ"G0Â#G Â&EÂ6EÂ7EÂ;1G Ã,GÃ-G ÄG ÄG
ÄG Ä!2G0ÅG0ÅEÅ	GÅ")G ÆFÆ.G Æ:G Ç GÇG Ç
G ÇG-Ç%G(Ç&G-Ç-G0c              ƒ  óø   K  — | r| j                  d«      du ry t        | j                  d«      xs d«      }t        |xs d«      }t        | j                  d«      xs g ||¬«      ƒ d {  –—†  |rd| d<   y y 7 Œ­w)Nr‘   Tr�   r�   r[   )r[   Úactual_costrj   )r]   r+   Ú!_set_reserved_entries_actual_cost)r`   r¦   Úfinalizer�   Úactuals        r<   Úreconcile_budget_reservationrª     s�   è ø€ ñ
 Ð!3×!7Ñ!7¸Ó!DÈÑ!LØä Ð!3×!7Ñ!7¸Ó!HÒ!OÈCÓP€MÜ˜+Ò,¨Ó-€FÜ
+Ø"×&Ñ& yÓ1Ò7°RØØ+ô÷ ð ñ
 Ø*.Ð˜;Ò'ð ðús   ‚A(A:Á*A8Á+A:c              ƒ  ó:   K  — t        | d¬«      ƒ d {  –—†  y 7 Œ­w)Nr�   ©r`   r¦   )rª   ©r`   s    r<   Úrelease_budget_reservationr®   *  s   è ø€ Ü
&Ø-Øô÷ ò ús   ‚“”c              ƒ  ó  K  — | r| j                  d«      du ryt        | j                  d«      xs d«      }	 t        j                  t	        | |¬«      «      ƒ d{  –—†  y7 Œ# t        j
                  t        f$ r Y yw xY w­w)al  Reconcile a still-open reservation when the request is cancelled mid-flight.

    A client disconnect or timeout cancels the request task, which surfaces as
    CancelledError / GeneratorExit rather than a normal exception, so neither the
    success cost callback nor the failure hook runs and the pre-call reservation
    is never reconciled. Left alone it pins the spend counter above real spend
    and 429s subsequent requests until the counter's TTL expires.

    Reconcile to the request's input-token cost rather than refunding to zero:
    by the time a request is cancelled in-flight the provider call was already
    dispatched, so the input tokens were billed even if no chunk reached the
    client. Refunding to zero would let a caller abort pre-token to dodge that
    charge; the worst-case output portion of the reservation is still released.

    asyncio.shield keeps the reconcile running to completion even though the
    surrounding task is being cancelled. The `finalized` guard makes this a no-op
    when success/failure handling already reconciled, so calling it on every
    cancellation path is safe.
    r‘   TNr’   r�   r¬   )r]   r+   ÚasyncioÚshieldrª   ÚCancelledErrorr›   )r`   Úincurred_costs     r<   Ú$release_budget_reservation_on_cancelr´   1  s�   è ø€ ñ, Ð!3×!7Ñ!7¸Ó!DÈÑ!LØÜ Ð!3×!7Ñ!7¸Ó!EÒ!LÈÓM€MðÜ�n‰nÜ(Ð<NÐ\iÔjó
÷ 	
ò 	
ùô ×"Ñ"¤IÐ.ò Ùðüs:   ‚5B¸#A# ÁA!ÁA# Á BÁ!A# Á#A?Á<BÁ>A?Á?Bc              ƒ  óf   K  — | €y ddl m} t        | ¬«      D ]  } ||¬«      ƒ d {  –—†  Œ y 7 Œ­w)Nr   ©Ú_invalidate_spend_counterr­   rX   )Úlitellm.proxy.proxy_serverr·   rb   )r`   r·   r*   s      r<   Ú&invalidate_budget_reservation_countersr¹   R  s<   è ø€ ð Ð!ØåDä0ÐDVÔWò AˆÙ'°KÔ@×@Ñ@ñAØ@ús   ‚%1§/¨1c
              ƒ  ón  K  — g }
|j                   �Ý|j                  �z|j                  dkD  rk|
j                  t        d|j                   › �|j                   t	        |j                  «      t	        |j
                  xs d«      d|j                   ¬«      «       |
j                  t        d|j                   › �d|j                   |j                  t	        |j
                  xs d«      ¬«      «       |�Æ|j                  �º|j                  }|j                  �_|j                  dkD  rP|
j                  t        d|› �d|› �t	        |j                  «      t	        |j
                  xs d«      d	|¬«      «       |
j                  t        d|› �d	||j                  t	        |j
                  xs d«      ¬«      «       |d uxr |j                  d u}|r|	r”|�’|j                  �†|j                  �z|j                  dkD  rk|
j                  t        d
|j                  › �|j                  t	        |j                  «      t	        |j
                  xs d«      d|j                  ¬«      «       t        |||¬«      ƒ d {  –—† }|�|
j                  |«       |
j                  t        | |||¬«      ƒ d {  –—† «       |
j                  t        |||¬«      ƒ d {  –—† «       t        ||||¬«      ƒ d {  –—† }|�|
j                  |«       t        |||¬«      ƒ d {  –—† }|�|
j                  |«       |
S 7 Œ·7 Œ„7 Œa7 ŒH7 Œ!­w)Nr   rd   r�   r=   ©r*   r1   r,   r-   r.   r/   )Úentity_prefixr.   r/   Úbudget_limitsr-   zspend:team:zteam_id:r>   zspend:user:r@   )rf   r‰   rŠ   )rƒ   r†   r‡   rˆ   )rf   r†   r‡   )rf   r„   r…   r‡   )rf   r„   r‡   )re   r,   r˜   r(   r+   ÚspendÚextendÚ_get_budget_limit_countersr½   Úteam_idÚuser_idÚ_get_end_user_budget_counterÚ_get_tag_budget_countersÚ'_get_model_access_group_budget_countersÚ_get_team_member_budget_counterÚ_get_org_budget_counter)rƒ   rf   r„   r…   r†   r‡   rˆ   r‰   rŠ   r‹   rŸ   rÁ   Úis_team_keyÚend_user_counterÚteam_member_counterÚorg_counters                   r<   r”   r”   ^  sK  è ø€ ð -/€Hà×ÑÐ$Ø×!Ñ!Ð-°+×2HÑ2HÈ1Ò2LØ�O‰OÜØ",¨[×->Ñ->Ð,?Ð @Ø%0×%6Ñ%6Ü$ [×%;Ñ%;Ó<Ü#(¨×):Ñ):Ò)A¸cÓ#BØ %Ø)×/Ñ/ôô	ð 	�‰Ü&Ø *¨;×+<Ñ+<Ð*=Ð>Ø!Ø%×+Ñ+Ø)×7Ñ7Ü$ [×%6Ñ%6Ò%=¸#Ó>ôô	
ð Ð ;×#6Ñ#6Ð#BØ$×,Ñ,ˆØ×!Ñ!Ð-°+×2HÑ2HÈ1Ò2LØ�O‰OÜØ"-¨g¨YÐ 7Ø'/°¨yÐ%9Ü$ [×%;Ñ%;Ó<Ü#(¨×):Ñ):Ò)A¸cÓ#BØ &Ø%ôô	ð 	�‰Ü&Ø +¨G¨9Ð5Ø"Ø!Ø)×7Ñ7Ü$ [×%6Ñ%6Ò%=¸#Ó>ôô	
ð %¨DÐ0ÒT°[×5HÑ5HÐPTÐ5T€KáÑ:ØÐ#Ø×ÑÐ+Ø×"Ñ"Ð.Ø×"Ñ" QÒ&à�‰ÜØ)¨+×*=Ñ*=Ð)>Ð?Ø!,×!4Ñ!4Ü  ×!7Ñ!7Ó8Ü$ [×%6Ñ%6Ò%=¸#Ó>Ø"Ø%×-Ñ-ôô		
ô %AØØØ'ô%÷ Ðð
 Ð#Ø�‰Ð(Ô)à‡O�OÜ&Ø%Ø'Ø1Ø/ô	
÷ 	
ôð ‡O�OÜ5Ø#Ø'Ø1ô
÷ 	
ôô (GØØØØ-ô	(÷ "Ðð Ð&Ø�‰Ð+Ô,ä6ØØØ-ô ÷ €Kð
 ÐØ�‰˜Ô$à€OðUøð	
øð	
øð"øðúsZ   ‚I1L5É3L+É44L5Ê(L-Ê)$L5ËL/ËL5Ë(L1Ë)(L5ÌL3ÌL5Ì-L5Ì/L5Ì1L5Ì3L5c              ƒ  ó(  K  — |xs | j                   }|€y t        |«      }t        | j                  «      }d}|�<t        t	        |d«      «      xs d}|€!t	        |d«      }t        t	        |d«      «      }|�|dk  ry t        d|› �|||d|¬«      S ­w)	Nr�   r¾   Úlitellm_budget_tabler,   r   zspend:end_user:rA   r»   )r‰   r   Ú	_to_floatÚend_user_max_budgetÚ
_get_valuer(   )rf   r‰   rŠ   r1   r,   r-   Úbudget_tables          r<   rÃ   rÃ   Ù  s¶   è ø€ ð
 Ò8 ×!8Ñ!8€KØÐØä0°Ó=ÐÜ˜;×:Ñ:Ó;€JØ€NØÐ"Ü"¤:¨o¸wÓ#GÓHÒOÈCˆØÐÜ",¨_Ð>TÓ"UˆLÜ"¤:¨l¸LÓ#IÓJˆJàÐ˜Z¨1š_ØäØ% k ]Ð3Ø)ØØ%ØØôð ùs   ‚BBc              ƒ  ó�  K  — ddl m} ddlm} t	         || ¬«      «      }|sg S  |||||¬«      ƒ d {  –—† }g }|D ]‚  }	|j                  |	«      }
|
€Œt        |
d«      }t        t        |d«      «      }|�|dk  rŒ@|j                  t        d|	› �t        |	«      |t        t        |
d	«      «      xs d
d|	¬«      «       Œ„ |S 7 Œ�­w)Nr   )Úget_tag_objects_batch)Úget_tags_from_request_body©rƒ   )Ú	tag_namesr†   r‡   rˆ   rÍ   r,   z
spend:tag:r¾   r�   rB   r»   )Úlitellm.proxy.auth.auth_checksrÓ   Ú-litellm.proxy.common_utils.http_parsing_utilsrÔ   Ú_dedupe_tagsr]   rÐ   rÎ   r˜   r(   r!   )rƒ   r†   r‡   rˆ   rÓ   rÔ   rÖ   Útag_objectsrŸ   Útag_nameÚ
tag_objectrÑ   r,   s                r<   rÄ   rÄ   ø  së   è ø€ õ EÝXä#Ñ$>ÈLÔ$YÓZ€IÙØˆ	á4ØØ#Ø-Ø+ô	 ÷ €Kð -/€HØò 
ˆØ —_‘_ XÓ.ˆ
ØÐØÜ! *Ð.DÓEˆÜœz¨,¸ÓEÓFˆ
ØÐ ¨q¢ØØ�‰ÜØ(¨¨
Ð3Ü!.¨xÓ!8Ø%Ü(¬°JÀÓ)HÓIÒPÈSØ!Ø"ôõ		
ð
ð$ €Oð5ús   ‚2C´CµBCc              ƒ  óè   ‡K  — ddl m} t        t        j	                  | j
                  xs d«      «      }|sg S  ||||¬«      ƒ d{  –—† Šˆfd„|D «       }|D �cg c]  }|€Œ|‘Œ	 c}S 7 Œ"c c}w ­w)ah  Reservation counters for the model access groups that authorized this request.

    The names come off the auth object rather than the request body: ``common_checks`` already
    resolved which granted groups serve the requested model, and re-deriving that here would both
    duplicate the walk and risk disagreeing with what the spend writer attributes.
    r   )Ú$get_model_access_group_budgets_batchr:   )Úaccess_group_namesr†   r‡   Nc              3  óT   •K  — | ]  }t        |‰j                  |«      «      –— Œ! y ­w©N)Ú_model_access_group_counterr]   )Ú.0ÚgroupÚbudgetss     €r<   ú	<genexpr>z:_get_model_access_group_budget_counters.<locals>.<genexpr>8  s#   øè ø€ ÒiÐTYÔ4°U¸G¿K¹KÈÓ<N×OÑiùs   ƒ%()r×   rÞ   Útupler_   ÚfromkeysÚmatched_model_access_groups)rf   r†   r‡   rÞ   Úgroup_namesÚ
candidatesru   rå   s          @r<   rÅ   rÅ   "  s{   øè ø€ õ TäœtŸ}™}¨[×-TÑ-TÒ-ZÐXZÓ[Ó\€KÙØˆ	á?Ø&Ø#Ø-ô÷ €Gó
 jÐ]hÔi€JØ#-ÖE˜°Ñ1DŠGÒEÐEðúò Fùs*   ƒAA2ÁA+Á	A2ÁA-Á$A-Á(A2Á-A2c                ó¬   — |�|j                   �|j                   dk  ryt        t        | «      t        | «      |j                   |j                  d| ¬«      S )zXA counter for one group, or nothing when the group carries no budget to reserve against.Nr   rC   r»   )r,   r(   r    r   r¾   )rä   Úbudgets     r<   râ   râ   <  sU   € à€~˜×*Ñ*Ð2°f×6GÑ6GÈ1Ò6LØÜÜ8¸Ó?Ü5°eÓ<Ø×$Ñ$Ø—|‘|Ø(Øôð r;   c                óz   — t        «       }g }| D ])  }||v rŒ|j                  |«       |j                  |«       Œ+ |S rá   )r\   Úaddr˜   )ÚtagsÚseenÚdeduped_tagsÚtags       r<   rÙ   rÙ   J  sH   € Ü“%€DØ€LØò !ˆØ�$‰;ØØ�‰�ŒØ×Ñ˜CÕ ð	!ð
 Ðr;   c           
   ƒ  ó4  K  — |�|j                   �|�| j                  €y t        | j                  |j                   ¬«      }|j                  |¬«      ƒ d {  –—† }d }t	        |t
        «      r|}nt	        |t        «      rt        di |¤Ž}d }|�#|j                  �|j                  j                  }na|j                  xs i j                  d«      }t	        |t        «      r2|j                  d|› �¬«      ƒ d {  –—† }	t        t        |	d«      «      }|�|dk  ry |�t        t
        |«      j                  nd}
t!        d| j                  › d	|j                   › �|t#        |«      t#        |
xs d«      d
| j                  › d	|j                   › �¬«      S 7 �Œ=7 Œœ­w)N)rÂ   rÁ   ©ÚkeyÚteam_member_budget_idzteam_member_default_budget:r,   r   r�   zspend:team_member:ú:r?   r»   r:   )rÁ   rÂ   r"   Úasync_get_cacher^   r   r_   rÍ   r,   Úmetadatar]   r)   rÎ   rÐ   r   r¾   r(   r+   )rf   r„   r…   r‡   Úmembership_cache_keyÚcached_team_membershipÚteam_membershipÚteam_member_budgetÚdefault_budget_idÚdefault_budgetÚteam_member_spends              r<   rÆ   rÆ   U  s»  è ø€ ð Ð˜k×1Ñ1Ð9¸[Ð=PÐT_×TgÑTgÐToØä"GØ×#Ñ#¨[×-@Ñ-@ô#Ðð +=×*LÑ*LÐQeÐ*LÓ*f×$fÐØ59€OÜÐ(Ô*@ÔAØ0‰Ü	Ð*¬DÔ	1Ü0ÑJÐ3IÑJˆà'+ÐØÐ" ×'KÑ'KÐ'WØ,×AÑA×LÑLÑà$/×$8Ñ$8Ò$>¸B×#CÑ#CÐD[Ó#\ÐÜÐ'¬Ô-Ø*<×*LÑ*LØ1Ð2CÐ1DÐEð +Mó +÷ %ˆNô "+¬:°nÀlÓ+SÓ!TÐàÐ!Ð%7¸1Ò%<ØàO^ÐOjœÔ3°_ÓE×KÒKÐpsÐÜØ(¨×)<Ñ)<Ð(=¸Q¸{×?RÑ?RÐ>SÐTØ-ÜÐ+Ó,ÜÐ.Ò5°#Ó6Ø Ø ×(Ñ(Ð)¨¨;×+>Ñ+>Ð*?Ð@ôð ð- %gùð%ús&   ‚AFÁFÁB"FÃ9FÃ:BFÆFc              ƒ  óz  K  — d }| j                   �| j                   }n|�|j                  �|j                  }|€y |j                  d|› d�¬«      ƒ d {  –—† }|€y t        |d«      }|€y t	        t        |d«      «      }|�|dk  ry t	        t        |d«      «      xs d}t        d	|› �d|› d�||d
|¬«      S 7 Œd­w)Nzorg_id:z:with_budgetrõ   rÍ   r,   r   r¾   r�   z
spend:org:rD   r»   )Úorg_idÚorganization_idrù   rÐ   rÎ   r(   )rf   r„   r‡   r  Ú	org_tableÚorg_budget_tableÚorg_max_budgetÚ	org_spends           r<   rÇ   rÇ   �  sý   è ø€ ð
 €FØ×ÑÐ%Ø×#Ñ#‰Ø	Ð	  [×%@Ñ%@Ð%LØ×,Ñ,ˆØ€~Øà/×?Ñ?Ø�f�X˜\Ð*ð @ó ÷ €Ið ÐØä(¨Ð4JÓKÐØÐØä%¤jÐ1AÀ<Ó&PÓQ€NØÐ °1Ò!4Øä ¤¨I°wÓ!?Ó@ÒGÀC€IÜØ   Ð)Ø" 6 (¨,Ð7Ø!Ø Ø"Øôð ðús   ‚AB;ÁB9ÁA%B;c                óV  — g }|s|S |D ]�  }t        |«      }|j                  d«      }|j                  d«      }	|r|	�|	dk  rŒ:t        |«      }
|
€t        j                  d|||«       Œ`|j                  t        | › d|› �t        |	«      d||› d|› �|t        |«      |
¬«      «       ŒŸ |S )	NÚbudget_durationr,   r   z:Skipping budget window with invalid duration for %s=%s: %sz:window:r�   rø   )r*   r,   r-   r.   r/   r2   r3   r5   )	Ú_coerce_windowr]   Úget_budget_window_startr   rV   r˜   r(   r+   r)   )r¼   r.   r/   r½   r-   rŸ   ÚwindowÚwindow_dictr
  r,   r5   s              r<   rÀ   rÀ   §  sÜ   € ð -/€HÙØˆàò 
ˆÜ$ VÓ,ˆØ%Ÿ/™/Ð*;Ó<ˆØ —_‘_ \Ó2ˆ
Ù *Ð"4¸
ÀaºØÜ.¨{Ó;ˆØÐÜ ×(Ñ(ØLØØØô	ð Ø�‰ÜØ,˜o¨X°oÐ5FÐGÜ  Ó,Ø"Ø'Ø&˜K q¨Ð(9Ð:Ø$-Ü # OÓ 4Ø)ô	õ	
ð
ð6 €Or;   c                óø   — t        | t        «      r| S t        | t        «      r*	 t        j                  | «      }t        |t        «      r|S i S t        | d«      r| j                  «       S i S # t
        $ r i cY S w xY w)NÚ
model_dump)r^   r_   r)   ÚjsonÚloadsr›   Úhasattrr  )r  Úparseds     r<   r  r  Ð  sx   € Ü�&œ$ÔØˆÜ�&œ#Ôð	Ü ŸJ™J vÓ.ˆFÜ'¨´Ô5�6Ð=¸2Ð=ô ˆv�|Ô$Ø× Ñ Ó"Ð"Ø€Iøô	 ò 	ØŠIð	ús   ¤&A+ ÁA+ Á+A9Á8A9c              ƒ  ó6  K  — ddl m}m}m}m} d}	 | j
                  �' || j                  | j
                  ¬«      ƒ d {  –—†  n‰| j                  �}| j                  �q || j                  | j                  | j                  | j                  | j                  ¬«      ƒ d {  –—† }|du r&t        j                  d| j                  «       t        ‚d} || j                  |¬«      ƒ d {  –—† }|�t        |«      S d S 7 Œ»7 Œ]7 Œ# t        $ r ‚ t        $ rƒ t        j                  d	| j                  d¬
«       d}		  || j                  ¬«      ƒ d {  –—†7   d}	n1# t        $ r% t        j                  d| j                  d¬
«       Y nw xY wt        ||	¬«      ‚w xY w­w)Nr   )Ú!_ensure_spend_counter_initializedÚ(_ensure_window_spend_counter_initializedÚ_increment_spend_counter_cacher·   F)r*   r1   )r*   r.   r/   r3   r5   zKSkipping budget reservation for %s because window spend could not be loadedT©r*   Ú	incrementzKSkipping budget reservation for %s because spend counter reservation failed©Úexc_inforX   zJFailed to invalidate spend counter after budget reservation failure for %s)rI   rJ   )r¸   r  r  r  r·   r1   r*   r2   r5   r.   r3   r   rV   rG   r+   r›   )
ru   rw   r  r  r  r·   Úattempted_incrementÚinitializedr¡   rJ   s
             r<   r™   r™   Þ  s·  è ø€ ÷ó ð  Ðð0
Ø×#Ñ#Ð/Ù3Ø#×/Ñ/Ø!(×!9Ñ!9ô÷ ñ ð ×(Ñ(Ð4¸×9MÑ9MÐ9YÙ'OØ#×/Ñ/Ø#×/Ñ/Ø!×5Ñ5Ø '× 7Ñ 7Ø$×1Ñ1ô(÷ "ˆKð ˜eÑ#Ü$×,Ñ,ØaØ×'Ñ'ôô 5Ð4à"ÐÙ&DØ×+Ñ+Ø&ô'
÷ !
ˆð )7Ð(BŒu�^Ó$ÐLÈÐLð1øð
"øð!
ùô
 *ò ØÜò 
Ü×$Ñ$ØYØ×ÑØõ	
ð
 $Ðð	Ù+¸×8KÑ8KÔL×LÑLØ"&ÑøÜò 	Ü ×(Ñ(Ø\Ø×#Ñ#Ø÷ð	úô -Ø/Ø 3ô
ð 	
ð!
üs�   ‚F’-D ¿C;Á AD ÂC=Â AD Ã'C?Ã(D Ã8FÃ9D Ã:FÃ;D Ã=D Ã?D Ä6FÄ8EÅEÅEÅFÅ+FÆFÆFÆFÆFc              ƒ  óf   K  — ddl m}  || j                  | j                  ¬«      ƒ d {  –—† S 7 Œ­w)Nr   )Úget_current_spend)r*   r-   )r¸   r   r*   r-   )ru   r   s     r<   rš   rš     s2   è ø€ Ý<á"Ø×'Ñ'Ø×-Ñ-ô÷ ð ð ús   ‚(1ª/«1c              ƒ  óL   K  — | D ]  }t        ||||¬«      ƒ d {  –—†  Œ y 7 Œ­w)N)ra   r¦   rj   Úreseed_on_inconsistent)Ú_set_reserved_entry_actual_cost)r[   r¦   rj   r"  ra   s        r<   r§   r§   &  s:   è ø€ ð ò 
ˆÜ-ØØ#Ø"7Ø#9ô	
÷ 	
ñ 	
ñ
ð	
ús   ‚$š"›$c              ƒ  ód  K  — ddl m}m} | j                  d«      }|€y t	        | |¬«      }||z
  }t        | j                  d«      xs d«      }	||	z
  }
|
dk(  ry t        ||
¬«      ƒ d {  –—† r |||
¬«      ƒ d {  –—†  n"|r ||¬	«      ƒ d {  –—†  nt        d
|› �«      ‚|| d<   y 7 Œ?7 Œ/7 Œ­w)Nr   )r  Úreseed_spend_counter_from_dbr*   ©ra   rj   Úapplied_adjustmentr�   )r*   Ú
adjustmentr  rX   z>Cannot resize budget reservation against inconsistent counter )r¸   r  r%  r]   Ú_get_entry_reserved_costr+   Ú_counter_can_apply_adjustmentÚRuntimeError)ra   r¦   rj   r"  r  r%  r*   r�   Útarget_adjustmentr'  r(  s              r<   r#  r#  5  së   è ø€ ÷ð
 Ÿ™ =Ó1€KØÐØÜ3ØØ3ô€Mð  +¨]Ñ:ÐÜ % e§i¡iÐ0DÓ&EÒ&LÈÓ MÐØ)Ð,>Ñ>€JØ�Q‚ØÜ*ØØô÷ ð ñ -Ø#Ø ô
÷ 	
ñ 	
ñ 
 ñ +°{ÔC×CÑCô Ð[Ð\gÐ[hÐiÓjÐjØ"3€EÐ
Òð-øð	
øð 	Dús6   ‚A(B0Á*B*Á+B0Á<B,Á=B0ÂB.ÂB0Â,B0Â.B0c              ƒ  ó¶   K  — ddl m} |j                  | ¬«      ƒ d {  –—† }|€y	 t        |«      }|dk  xr ||z   dk   S 7 Œ## t        t
        f$ r Y yw xY w­w)Nr   )Úspend_counter_cacherõ   Fgê-�™—q½)r¸   r.  rù   r+   Ú	TypeErrorÚ
ValueError)r*   r(  r.  Úcurrent_valueÚcurrent_floats        r<   r*  r*  e  su   è ø€ õ ?à!4×!DÑ!DÈÐ!DÓ!U×U€MØÐØðÜ$ ]Ó3ˆð ˜Q‘ÒF =°:Ñ#=ÀÑ#FÐGÐGð Vùô ”zÐ"ò Ùðüs1   ‚AžAŸA§A ²AÁAÁAÁAÁAc              ƒ  ó:  K  — | D ]  }	 t        |d|¬«      ƒ d {  –—†  Œ y 7 Œ# t        $ rk |j                  d«      }t        j                  d«       |€Y ŒR	 ddlm}  ||¬«      ƒ d {  –—†7   n$# t        $ r t        j                  d«       Y nw xY wY Œ’w xY w­w)	Nr�   )ra   r¦   rj   r*   zEFailed to release partial budget reservation during exception cleanupr   r¶   rX   zPFailed to invalidate partial budget reservation counter during exception cleanup)r#  r›   r]   r   Ú	exceptionr¸   r·   )r[   rj   ra   r*   r·   s        r<   rp   rp   w  s¨   è ø€ ð ò ˆð	Ü1ØØØ&;ô÷ ñ ñðùô
 ò 	ØŸ)™) MÓ2ˆKÜ ×*Ñ*Ð+rÔsØÐ"ÙðÝPá/¸KÔH×HÒHøÜò Ü$×.Ñ.Øföðüð	üsg   ‚B‰$š"›$ŸB¢$¤1BÁBÁA1Á*A-Á+A1Á0BÁ1BÂBÂBÂBÂBÂBÂBc              ƒ  ó`   K  — t        | ||d¬«      ƒ d {  –—†  | D ]  }||d<   d|d<   Œ y 7 Œ­w)NF)r[   r¦   rj   r"  r�   r�   r'  )r§   )r[   rk   rl   ra   s       r<   rr   rr   ‘  sQ   è ø€ ô
 ,ØØ%Ø3Ø$ô	÷ ð ð ò *ˆØ!2ˆˆoÑØ&)ˆÐ"Ò#ñ*ðús   ‚.•,–.c                óN   — | j                   | j                  | j                  |ddœS )Nr�   )r*   r.   r/   r�   r'  )r*   r.   r/   rŽ   s     r<   r—   r—   ¡  s/   € ð
 ×*Ñ*Ø×*Ñ*Ø×&Ñ&Ø&Ø!ñð r;   c                óp   — 	 t        | j                  d|«      xs d«      S # t        t        f$ r |cY S w xY w)Nr�   r�   )r+   r]   r/  r0  r&  s     r<   r)  r)  ®  s=   € ð%Ü�U—Y‘Y˜Ð0EÓFÒMÈ#ÓNÐNøÜ”zÐ"ò %Ø$Ò$ð%ús   ‚! ¡5´5c                ó–  — t        | «      }|j                  d«      }|€y 	 t        t        |«      «      }t        |j                  d«      «      }|€0t        j                  t        j                  «      t        |¬«      z
  S |j                  € |j                  t        j                  ¬«      }|t        |¬«      z
  S # t        $ r Y y w xY w)Nr
  Úreset_at)Úseconds)Útzinfo)r  r]   r   r)   r›   Ú_coerce_datetimer   Únowr	   Úutcr   r;  Úreplace)r  r  r
  Úduration_secondsr9  s        r<   r  r  µ  s¸   € Ü'¨Ó/€KØ(Ÿ_™_Ð->Ó?€OØÐØðÜ"5´c¸/Ó6JÓ"KÐô   §¡°
Ó ;Ó<€HØÐÜ�|‰|œHŸL™LÓ)¬IÐ>NÔ,OÑOÐOØ‡�ÐØ×#Ñ#¬8¯<©<Ð#Ó8ˆØ”iÐ(8Ô9Ñ9Ð9øô ò Ùðús   ¡B< Â<	CÃCc                ó¸   — | €y t        | t        «      r| S t        | t        «      r&	 t        j                  | j	                  dd«      «      S y # t
        $ r Y y w xY w)NÚZz+00:00)r^   r   r)   Úfromisoformatr?  r0  ©Úvalues    r<   r<  r<  Ç  s]   € Ø€}ØÜ�%œÔ"ØˆÜ�%œÔð	Ü×)Ñ)¨%¯-©-¸¸XÓ*FÓGÐGð øô ò 	Ùð	ús   §$A Á	AÁAc                óø   — t        | ||¬«      D �cg c]%  }t        | ||||xs i j                  |«      ¬«      ‘Œ' }}|D �cg c]  }|€Œ|‘Œ	 }}|sy t        t	        t
        t           |«      «      S c c}w c c}w )NrŒ   ©rƒ   r}   Úmodelr‚   Úinput_tokens)Ú_get_request_modelsÚ$_estimate_request_max_cost_for_modelr]   Úmaxr   Úlistr+   ©rƒ   r}   r‚   r�   Ú
model_nameÚ	estimatesÚestimates          r<   r–   r–   Ô  s’   € ô .¸<ÈuÐakÔlö	ð ô 	-Ø%ØØØ!Ø,Ò2°×7Ñ7¸
ÓCö	
ð	€Ið 	ð +4ÖL˜h°xÑ7K’ÐL€IÐLÙØÜŒt”Dœ‘K Ó+Ó,Ð,ùò	ùò Ms   ‘*A2ÁA7Á	A7c                óâ   — t        | ||¬«      D �cg c]%  }t        | ||||xs i j                  |«      ¬«      ‘Œ' }}|D �cg c]  }|€Œ|‘Œ	 }}|syt        t	        d|«      «      S c c}w c c}w )aY  Cost of the request's input tokens alone.

    Once the provider request is dispatched the input tokens are billed even if
    the client disconnects before the first chunk, so this is the cost floor a
    cancelled in-flight request has already incurred. A cancelled reservation is
    reconciled to this instead of being refunded to zero.
    rŒ   rG  Nzlist[float])rJ  Ú&_estimate_request_input_cost_for_modelr]   rL  r   rN  s          r<   rœ   rœ   ê  sŽ   € ô* .¸<ÈuÐakÔlö	ð ô 	/Ø%ØØØ!Ø,Ò2°×7Ñ7¸
ÓCö	
ð	€Ið 	ð +4ÖL˜h°xÑ7K’ÐL€IÐLÙØÜŒt�M 9Ó-Ó.Ð.ùò	ùò Ms   ‘*A'ÁA,Á	A,c           
     ó¨   — t        ||¬«      D �cg c]  }t        | ||||¬«      ‘Œ }}|D �cg c]  }|€Œ|‘Œ	 }}|rt        |«      S d S c c}w c c}w ©N©rH  r‚   ©rƒ   r}   rH  Ú
model_inforI  )Ú_get_model_cost_infosÚ_input_cost_for_cost_inforL  ©	rƒ   r}   rH  r‚   rI  rX  rP  rQ  Úvalid_estimatess	            r<   rS  rS    sv   € ô 0°eÈ
ÔSö	ð ô 	"Ø%ØØØ!Ø%ö	
ð	€Ið 	ð 8AÖY¨8ÀHÑDXšhÐY€OÐYÙ#2Œ3ˆÓÐ<¸Ð<ùò	ùò Zó   �A
­AµAc                óî   — t        | ||||¬«      }|€y |j                  d«      }t        |t        «      r |rt	        ||¬«      }|�|t        |d«      z  S t        |j                  d«      «      }|€y ||z  S )NrW  Útiered_pricing©r_  rI  Úinput_cost_per_token)Ú_estimate_input_tokensr]   r^   rM  r   r   rÎ   )	rƒ   r}   rH  rX  rI  Úestimated_input_tokensr_  Útierra  s	            r<   rZ  rZ    s”   € ô %;Ø!ØØØØ!ô%Ðð Ð%ØØ&ŸN™NÐ+;Ó<€NÜ�.¤$Ô'©NÜ+¸>ÐXnÔoˆØÐØ)¬I°dÐ<RÓ,SÑSÐSÜ"+¨J¯N©NÐ;QÓ,RÓ"SÐØÐ#ØØ!Ð$8Ñ8Ð8r;   c           
     ó¨   — t        ||¬«      D �cg c]  }t        | ||||¬«      ‘Œ }}|D �cg c]  }|€Œ|‘Œ	 }}|rt        |«      S d S c c}w c c}w rU  )rY  Ú_max_cost_for_cost_inforL  r[  s	            r<   rK  rK  7  sv   € ô 0°eÈ
ÔSö	ð ô 	 Ø%ØØØ!Ø%ö	
ð	€Ið 	ð 8AÖY¨8ÀHÑDXšhÐY€OÐYÙ#2Œ3ˆÓÐ<¸Ð<ùò	ùò Zr]  c                ór  — t        | |¬«      }|�|S t        | ||||¬«      }t        | ||¬«      }|�|€y t        | ¬«      }|j	                  d«      }	t        |	t        «      rI|	rGt        |	|¬«      }
|
�8t        t        |
d«      t        |
d«      «      }|t        |
d	«      z  ||z  |z  z   S t        |j	                  d	«      «      }t        |j	                  d«      «      }t        |j	                  d«      «      }d
}|�	|||z  z  }n|dkD  ry t        |xs d
|xs d
«      }|€|�|||z  |z  z  }|S |dkD  ry |S )N)rƒ   rX  rW  )rƒ   r}   rX  rÕ   r_  r`  Úoutput_cost_per_tokenÚoutput_cost_per_reasoning_tokenra  r�   r   )Ú_estimate_image_generation_costrb  Ú_estimate_output_tokensÚ_get_output_multiplierr]   r^   rM  r   rL  r   rÎ   )rƒ   r}   rH  rX  rI  Ú
image_costrc  Úoutput_tokensÚoutput_multiplierr_  rd  Úoutput_ratera  rh  ri  Úcosts                   r<   rf  rf  L  s¡  € ô 8Ø!Øô€Jð ÐØÐä$:Ø!ØØØØ!ô%Ðô 3Ø!ØØô€Mð
 Ð%¨Ð)>Øä5À<ÔPÐØ&ŸN™NÐ+;Ó<€NÜ�.¤$Ô'©NÜ+¸>ÐXnÔoˆØÐÜÜ˜$Ð 7Ó8Ü˜$Ð AÓBóˆKð +¬Y°tÐ=SÓ-TÑTØÐ 1Ñ1°KÑ?ñð ô #,¨J¯N©NÐ;QÓ,RÓ"SÐÜ#,¨Z¯^©^Ð<SÓ-TÓ#UÐÜ-6°z·~±~ÐFgÓ7hÓ-iÐ#Ø€DØÐ'ØÐ&Ð)=Ñ=Ñ=‰Ø	 !Ò	#Øô
 Ð+Ò2¨sÐ4SÒ4ZÐWZÓ[€KØÐ(Ð,KÐ,WØ�Ð 1Ñ1°KÑ?Ñ?ˆð €Kð 
˜Ò	Øà€Kr;   c                ó  — |j                  d«      dvryt        |j                  d«      «      }t        |j                  d«      «      }|xs d|xs dz   }|dk  ryt        | j                  d«      «      xs d	}|t        |d	«      z  S )
uˆ  
    Reserve `n Ã— per-image cost` for image-generation requests so concurrent
    requests against a depleted budget cannot all slip past the admission gate
    onto the provider. Token-based pricing (e.g. gpt-image-1) is handled by
    the chat-route token path; per-pixel and size/quality-tiered pricing
    (DALL-E 2 size variants, premium tiers) are not handled here and fall
    through to read-time enforcement.

    The "output" vs "input" cost-per-image naming is inconsistent across
    providers â€” OpenAI's dall-e-3 entry uses ``input_cost_per_image`` while
    aiml/dall-e-3 uses ``output_cost_per_image`` â€” so both are summed.
    Úmode)Úimage_generationÚ
image_editNÚoutput_cost_per_imageÚinput_cost_per_imager�   r   Úné   )r]   rÎ   Ú_to_intrL  )rƒ   rX  rv  rw  Úcost_per_imagerx  s         r<   rj  rj  ‹  s�   € ð2 ‡~�~�fÓÐ%GÑGØä#,¨Z¯^©^Ð<SÓ-TÓ#UÐÜ"+¨J¯N©NÐ;QÓ,RÓ"SÐØ2Ò9°cÐ>RÒ>YÐVYÑZ€NØ˜ÒØä�|×'Ñ'¨Ó,Ó-Ò2°€AØœC  1›IÑ%Ð%r;   c                óŒ   — |�$|j                  | ¬«      }|�|j                  «       S t        t        j                  | ¬«      «      S )N)Úmodel_group)rH  )Úget_model_group_infor  r_   rs   Úget_model_info)rH  r‚   Úmodel_group_infos      r<   Ú_get_model_cost_infor�  ±  sI   € ð ÐØ",×"AÑ"AÈeÐ"AÓ"TÐØÐ'Ø#×.Ñ.Ó0Ð0Ü”×&Ñ&¨UÔ3Ó4Ð4r;   c                ó¸   ‡— 	 t        | |¬«      Š‰€g S t        | |¬«      }|s‰gS ‰gˆfd„|D «       ¢S # t        $ r t        j                  dd¬«       g cY S w xY w)aÇ  Cost-info candidates to estimate a request against for one model group.

    Reservation runs before routing, so the deployment that will serve the request
    is unknown. Rather than guess, we estimate the cost against every eligible
    pricing shape in the group (the group's flat rates plus each deployment's
    tiered table) and let the caller reserve the maximum, so a cheaper sibling
    deployment can never leave the request under-reserved.
    rV  z5Unable to load model cost info for budget reservationTr  c              3  ó.   •K  — | ]  }i ‰¥d |i¥–— Œ y­w)r_  Nr:   )rã   ÚtableÚbases     €r<   ræ   z(_get_model_cost_infos.<locals>.<genexpr>Õ  s   øè ø€ ÒQ¸%Ð5�tÐ5Ð-¨uÕ5ÑQùs   ƒ)r�  Ú%_get_deployment_tiered_pricing_tablesr›   r   Údebug)rH  r‚   Útiered_tablesr…  s      @r<   rY  rY  ¼  sw   ø€ ð
Ü*°À:ÔNˆØˆ<ØˆIÜDÈ5Ð]gÔhˆñ ØˆvˆØÐRÓQÀ=ÔQÐRÐRøô ò Ü×"Ñ"ØCØõ	
ð Š	ðús   ƒ4 ”4 ´"AÁAc                ó@  — | j                  di «      j                  d«      }| j                  di «      j                  d«      }t        |t        «      rt        |t        «      sy |j                  ||¬«      }|€y |j                  d«      }t        |t        «      r|r|S y )NrX  ÚidÚlitellm_paramsrH  )Úmodel_idrO  r_  )r]   r^   r)   Úget_deployment_model_inforM  )Ú
deploymentr‚   rŒ  Úbackend_modelÚdeployment_model_infor_  s         r<   Ú _deployment_tiered_pricing_tabler‘  Ø  s˜   € ð !—n‘n \°2Ó6×:Ñ:¸4Ó@€HØ%Ÿ>™>Ð*:¸BÓ?×CÑCÀGÓL€MÜ�h¤Ô$¬J°}ÄcÔ,JØØ#-×#GÑ#GÐQYÐfsÐ#GÓ#tÐØÐ$ØØ1×5Ñ5Ð6FÓG€NÜ�.¤$Ô'©NØÐØr;   c                ó|   — |€g S |j                  | ¬«      xs g }|D �cg c]  }t        ||«      x}�|‘Œ c}S c c}w )N)rO  )Úget_model_listr‘  )rH  r‚   ÚdeploymentsrŽ  r„  s        r<   r†  r†  é  s[   € ð ÐØˆ	Ø#×2Ñ2¸eÐ2ÓDÒJÈ€Kð &öàÜ5°jÀ*ÓMÐMˆEÐZò 	òð ùò s   Ÿ9c                ó`   — t        | ||¬«      }|€yt        |t        «      r|fS t        |«      S )Nr�   r:   )r   r^   r)   rç   )rƒ   r}   r‚   rH  s       r<   rJ  rJ  ÷  s4   € ô
 *¨,¸È*ÔU€EØ€}ØÜ! %¬Ô-ˆEˆ8Ð?´5¸³<Ð?r;   i0u  r   Ú!TOKENIZE_OFF_EVENT_LOOP_MIN_CHARSc              ƒ  óÊ   K  — t        | ||¬«      }|st        i «      S t        | «      t        k  rt	        | |¬«      S t        j                  t        | |¬«      ƒ d{  –—† S 7 Œ­w)ae  Input-token count per candidate model, counted once per request.

    Tokenizing is the reservation path's dominant CPU cost and is O(prompt), so
    counting a large prompt inline stalls every other request on the worker.
    Large prompts are counted in a worker thread, and the counts are reused by
    both the max-cost and the input-cost estimate.
    rŒ   )rƒ   ÚmodelsN)rJ  r
   Ú_approximate_input_sizer–  Ú_count_input_tokens_for_modelsr°   Ú	to_thread)rƒ   r}   r‚   r˜  s       r<   r•   r•     sg   è ø€ ô (°\ÈÐ[eÔf€FÙÜ Ó#Ð#Ü˜|Ó,Ô/PÒPÜ-¸<ÐPVÔWÐWÜ×"Ñ"Ü&Ø!Øô÷ ð ð ús   ‚AA#ÁA!ÁA#c           	     ó^   — t        |D �ci c]  }t        | |¬«      x}�||“Œ c}«      S c c}w )N©rƒ   rH  )r
   Ú_count_input_tokens)rƒ   r˜  rH  Útokenss       r<   rš  rš    sD   € ô ð  ö	
àÜ-¸<ÈuÔUÐU�Ðbð �6‰Mò	
óð ùò	
s   Š*)ÚmessagesÚpromptÚinputÚqueryÚ	documentsÚtoolsÚtool_choiceÚ_INPUT_SIZE_FIELDSc                ó4   ‡ — t        ˆ fd„t        D «       «      S )a  Length of the request's input text, a cheap stand-in for tokenizing cost.

    Every field _count_input_tokens hands the tokenizer is sized here, and
    rendering rather than walking keeps mapping keys in the total, which a tool
    schema's property names are.c           	   3  óf   •K  — | ](  }t        t        ‰j                  |d «      «      «      –— Œ* y­w)Ú N)Úlenr)   r]   )rã   Úfieldrƒ   s     €r<   ræ   z*_approximate_input_size.<locals>.<genexpr>3  s(   øè ø€ ÒU¸Œs”3�|×'Ñ'¨¨rÓ2Ó3×4ÑUùs   ƒ.1)Úsumr§  rÕ   s   `r<   r™  r™  -  s   ø€ ô ÓUÔBTÔUÓUÐUr;   c                óú  — 	 d| v rJt        j                  || j                  d«      xs g | j                  d«      | j                  d«      ¬«      S d| v rt        || j                  d«      ¬«      S d| v rt        || j                  d«      ¬«      S d| v sd	| v r=t        || j                  d«      ¬«      }t        || j                  d	«      ¬«      }||z   S 	 y # t        $ r t        j                  d
d¬«       Y y w xY w)Nr   r¥  r¦  )rH  r   r¥  r¦  r¡  ©rH  Útextr¢  r£  r¤  z3Unable to count input tokens for budget reservationTr  )rs   Útoken_counterr]   Ú_count_text_tokensr›   r   r‡  )rƒ   rH  Úquery_tokensÚdocument_tokenss       r<   rž  rž  6  s  € ðiØ˜Ñ%Ü×(Ñ(ØØ%×)Ñ)¨*Ó5Ò;¸Ø"×&Ñ& wÓ/Ø(×,Ñ,¨]Ó;ô	ð ð �|Ñ#Ü%¨E¸×8HÑ8HÈÓ8RÔSÐSØ�lÑ"Ü%¨E¸×8HÑ8HÈÓ8QÔRÐRØ�lÑ" k°\Ñ&AÜ"4¸5À|×GWÑGWÐX_ÓG`Ô"aˆLÜ%7ØØ!×%Ñ% kÓ2ô&ˆOð   /Ñ1Ð1ð 'Bð øô ò iÜ×"Ñ"Ð#XÐcgÖhØðiús%   ‚AC ÁC Á0C ÂAC Ã C:Ã9C:c                ój   — |�|nt        | |¬«      }|�|S t        |j                  d«      «      }|�|S y )Nr�  Úmax_input_tokens)rž  rz  r]   )rƒ   r}   rH  rX  rI  Úcountedr¶  s          r<   rb  rb  O  sN   € ð %Ð0‰Ô6IÐWcÐkpÔ6qð ð ÐØˆä% j§n¡nÐ5GÓ&HÓIÐØÐ#ØÐàr;   i @  Ú"DEFAULT_MAX_OUTPUT_TOKENS_FALLBACKc                óÖ   — t        |¬«      ryd }dD ]   }t        | j                  |«      «      }|€Œ  n t        |j                  d«      «      xs t        }|€t        }t	        ||«      S )Nr|   r   )Úmax_completion_tokensÚ
max_tokensÚmax_output_tokensr¼  )Ú_is_input_only_routerz  r]   r¸  r�   )rƒ   r}   rX  Ú	requestedrö   Úmodel_ceilings         r<   rk  rk  f  su   € ô
  %Õ(Øà €IØKò ˆÜ˜L×,Ñ,¨SÓ1Ó2ˆ	ØÑ Ùðô # :§>¡>Ð2EÓ#FÓGÒmÔKm€MØÐÜ6ˆ	Üˆy˜-Ó(Ð(r;   c                óL  — |€yd}|g}|r™|j                  «       }|€Œt        |t        «      r|j                  |«       Œ7t        |t        «      r.|t        j                  | t        j                  |«      ¬«      z  }Œu|t        j                  | t        |«      ¬«      z  }|rŒ™|S )Nr   r¯  )
Úpopr^   rM  r¿   r_   rs   r±  r  Údumpsr)   )rH  r°  Útoken_countÚstackÚitems        r<   r²  r²  ‚  sš   € Ø€|Øà€KØ�6€EÙ
Ø�y‰y‹{ˆØˆ<ØÜ�dœDÔ!Ø�L‰L˜ÔØÜ�dœDÔ!Øœ7×0Ñ0°uÄ4Ç:Á:ÈdÓCSÔTÑTˆKØØ”w×,Ñ,°5¼sÀ4»yÔIÑIˆò ð Ðr;   c                ój   — d}dD ]+  }t        | j                  |«      «      }|€Œ t        ||«      }Œ- |S )Nry  )rx  Úbest_of)rz  r]   rL  )rƒ   ro  rö   rE  s       r<   rl  rl  –  sH   € ØÐØò >ˆÜ˜×(Ñ(¨Ó-Ó.ˆØÑÜ #Ð$5°uÓ =Ñð>ð Ðr;   c                ó,   ‡ — t        ˆ fd„dD «       «      S )Nc              3  ó&   •K  — | ]  }|‰v –— Œ
 y ­wrá   r:   )rã   Ú
route_partr}   s     €r<   ræ   z'_is_input_only_route.<locals>.<genexpr>   s   øè ø€ ò àð 	�eÔñùs   ƒ)Ú
embeddingsÚrerankÚmoderations)Úanyr|   s   `r<   r½  r½  Ÿ  s   ø€ Üó ð
ôó ð r;   c                óJ   — | €y 	 t        | «      S # t        t        f$ r Y y w xY wrá   )r+   r/  r0  rD  s    r<   rÎ   rÎ   ª  s0   € Ø€}ØðÜ�U‹|ÐøÜ”zÐ"ò Ùðúó   …
 �"¡"c                óJ   — | €y 	 t        | «      S # t        t        f$ r Y y w xY wrá   )Úintr/  r0  rD  s    r<   rz  rz  ³  s0   € Ø€}ØðÜ�5‹zÐøÜ”zÐ"ò ÙðúrÐ  c                ó^   — t        | t        «      r| j                  |«      S t        | |d «      S rá   )r^   r_   r]   Úgetattr)Úobjrö   s     r<   rÐ   rÐ   ¼  s)   € Ü�#”tÔØ�w‰w�s‹|ÐÜ�3˜˜TÓ"Ð"r;   )r*   r)   rP   r   )r`   údict | NonerP   r\   )r*   r)   rf   úUserAPIKeyAuth | NonerP   rO   )ru   r(   rf   r×  ra   údict[str, float | str]rv   zlist[dict[str, float | str]]rw   r+   rx   r+   rP   r+   )NNFF)rƒ   r_   r}   r)   r‚   úRouter | Nonerf   r×  r„   úLiteLLM_TeamTable | Noner…   úLiteLLM_UserTable | Noner†   úPrismaClient | Noner‡   r   rˆ   r$   r‰   r0   rŠ   Úobjectr‹   rO   rž   rO   rP   rÖ  )T)r`   rÖ  r¦   úfloat | Noner¨   rO   rP   rQ   )r`   rÖ  rP   rQ   )NNF)rƒ   r_   rf   r   r„   rÚ  r…   rÛ  r†   rÜ  r‡   r   rˆ   r$   r‰   r0   rŠ   rÝ  r‹   rO   rP   úlist[_BudgetCounter])rf   r   r‰   r0   rŠ   rÝ  rP   ú_BudgetCounter | None)
rƒ   r_   r†   rÜ  r‡   r   rˆ   r$   rP   rß  )rf   r   r†   rÜ  r‡   r   rP   rß  )rä   r)   rí   zModelAccessGroupBudget | NonerP   rà  )rð   ú	list[str]rP   rá  )
rf   r   r„   rÚ  r…   rÛ  r‡   r   rP   rà  )rf   r   r„   rÚ  r‡   r   rP   rà  )r¼   r)   r.   r)   r/   r)   r½   zSequence[object] | Noner-   r+   rP   rß  )r  r   rP   r_   )ru   r(   rw   r+   rP   rÞ  )ru   r(   rP   r+   )
r[   ú
list[dict]r¦   r+   rj   r+   r"  rO   rP   rQ   )
ra   r_   r¦   r+   rj   r+   r"  rO   rP   rQ   )r*   r)   r(  r+   rP   rO   )r[   râ  rj   r+   rP   rQ   )r[   râ  rk   r+   rl   r+   rP   rQ   )ru   r(   r�   r+   rP   rØ  )ra   r_   rj   r+   rP   r+   )r  r   rP   r4   )rE  r   rP   r4   rá   )
rƒ   r_   r}   r)   r‚   rÙ  r�   zMapping[str, int] | NonerP   rÞ  )rƒ   r_   r}   r)   rH  r)   r‚   rÙ  rI  ú
int | NonerP   rÞ  )rƒ   r_   r}   r)   rH  r)   rX  úMapping[str, object]rI  rã  rP   rÞ  )rƒ   r_   rX  rä  rP   rÞ  )rH  r)   r‚   rÙ  rP   zMapping[str, object] | None)rH  r)   r‚   rÙ  rP   zSequence[Mapping[str, object]])rŽ  zdict[str, Any]r‚   r%   rP   zlist[dict] | None)rH  r)   r‚   rÙ  rP   z(Sequence[Sequence[Mapping[str, object]]])rƒ   r_   r}   r)   r‚   rÙ  rP   úSequence[str])rƒ   r_   r}   r)   r‚   rÙ  rP   úMapping[str, int])rƒ   r_   r˜  rå  rP   ræ  )rƒ   rä  rP   rÒ  )rƒ   r_   rH  r)   rP   rã  )rƒ   r_   r}   r)   rH  r)   rX  rä  rI  rã  rP   rã  )rƒ   r_   r}   r)   rX  rä  rP   rã  )rH  r)   r°  r   rP   rÒ  )rƒ   r_   rP   rÒ  )r}   r)   rP   rO   )rE  r   rP   rÞ  )rE  r   rP   rã  )rÕ  r   rö   r)   rP   r   )Ú
__future__r   r°   r  Úcollections.abcr   r   Údataclassesr   r   r   r	   Útypesr
   Útypingr   r   r   r   Úfastapir   r   rs   Úlitellm._loggingr   Ú*litellm.litellm_core_utils.duration_parserr   Ú7litellm.litellm_core_utils.llm_cost_calc.tiered_pricingr   r   Úlitellm.proxy._typesr   r   r   r   r   Úlitellm.proxy.auth.auth_utilsr   Ú"litellm.proxy.auth.budget_throttler   Úlitellm.proxy.auth.route_checksr   Ú-litellm.proxy.common_utils.user_api_key_cacher   r   r   r    r!   r"   Úlitellm.proxy.utilsr#   r$   Úlitellm.routerr%   Ú-litellm.types.proxy.model_access_group_budgetr&   r(   ÚKEYrE  ÚTEAMÚTEAM_MEMBERÚUSERÚEND_USERÚTAGÚMODEL_ACCESS_GROUPÚORGANIZATIONrE   r9   r›   rG   rY   rb   rg   rz   r¤   rª   r®   r´   r¹   r”   rÃ   rÄ   rÅ   râ   rÙ   rÆ   rÇ   rÀ   r  r™   rš   r§   r#  r*  rp   rr   r—   r)  r  r<  r–   rœ   rS  rZ  rK  rf  rj  r�  rY  r‘  r†  rJ  r–  r•   rš  r§  r™  rž  rb  r¸  rk  r²  rl  r½  rÎ   rz  rÐ   r:   r;   r<   ú<module>r      s©  ðÞ "ã Û ß -Ý !ß 2Ñ 2Ý "ß -Ó -ç )ã Ý 1Ý Jß d÷õ õ AÝ NÝ 7÷÷ ÷ ;Ý !Ý Pð ÷	)ð 	)ó ð	)ð ×!Ñ!×'Ñ'Ø×#Ñ#×)Ñ)Ø$×0Ñ0×6Ñ6Ø×#Ñ#×)Ñ)Ø!×*Ñ*×0Ñ0Ø×!Ñ!×'Ñ'Ø,×?Ñ?×EÑEØ&×3Ñ3×9Ñ9ñ	3Ð Ð/ó 	ô< Yô <óó ólð(Øð(à&ð(ð "ð(ð 2ð	(ð
 ð(ð ð(ð ó(ðj #Ø"Ø+0Ø+0ðvØðvàðvð ðvð 'ð	vð
 *ðvð *ðvð 'ðvð (ðvð $ðvð ðvð ðvð %)ðvð %)ðvð óvðx ð/Ø#ð/àð/ð ð/ð 
ó	/ó&ðØ#ðà	óðB	AØ#ð	Aà	ó	Að( #Ø"Ø+0ðxØðxàðxð *ðxð *ð	xð
 'ðxð (ðxð $ðxð ðxð ðxð %)ðxð óxðvØðàðð ðð ó	ð>'Øð'à&ð'ð (ð'ð $ð	'ð
 ó'ðTFØðFà&ðFð (ðFð ó	Fó4óð)Øð)à)ð)ð *ð)ð (ð	)ð
 ó)ðX#Øð#à)ð#ð (ð#ð ó	#ðL&Øð&àð&ð ð&ð +ð	&ð
 ð&ð ó&óRð<
Øð<
àð<
ð ó<
ó~ð $(ð	
Øð
àð
ð !ð
ð !ð	
ð
 
ó
ð& $(ð	-4Øð-4àð-4ð !ð-4ð !ð	-4ð
 
ó-4ð`HØðHàðHð 
óHð$Øðà ðð 
óð4*Øð*à ð*ð ð*ð 
ó	*ð 
Øð
àð
ð ó
ó%ó:ó$
ð" 48ð	-Øð-àð-ð ð-ð 1ð	-ð
 ó-ð4 48ð	/Øð/àð/ð ð/ð 1ð	/ð
 ó/ðD  $ð=Øð=àð=ð ð=ð ð	=ð
 ð=ð ó=ð4  $ð9Øð9àð9ð ð9ð %ð	9ð
 ð9ð ó9ð@  $ð=Øð=àð=ð ð=ð ð	=ð
 ð=ð ó=ð4  $ð<Øð<àð<ð ð<ð %ð	<ð
 ð<ð ó<ð~#&Øð#&à$ð#&ð ó#&ðL5Øð5àð5ð !ó5ðSØðSàðSð $óSð8Øðàðð óð"Øðàðð .óð@Øð@àð@ð ð@ð ó	@ð ,2Ð ! 5Ó 1ðØðàðð ðð ó	ð0
Øð
àð
ð ó
ð jÐ �EÓ ióVóð<  $ðØðàðð ðð %ð	ð
 ðð óð( -2Ð " EÓ 1ð)Øð)àð)ð %ð)ð ó	)ó8ó(óóóô#r;   