Ë
    tPêj.Š ã            
       óT  — U d Z ddlZddlZddlZddlZddlZddlZddlZddlm	Z	m
Z
 ddlmZmZmZ ddlmZmZmZmZmZmZmZ ddlZddl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(m)Z)m*Z*m+Z+m,Z,m-Z-m.Z.m/Z/m0Z0m1Z1 ddl2m3Z3m4Z4m5Z5 ddl6m7Z7 ddl8m9Z9 ddl:m;Z; ddl<m=Z= ddl>m?Z? ddl@mAZAmBZB ddlCmDZD ddlEmFZF ddlGmHZHmIZImJZJmKZK ddlLmMZM ddlNmOZO ddlPmQZQ er	ddlRmSZSmTZT neZSeZT eUeQj¬                  j®                  eQj°                  j®                  h«      ZYeeZd<    G d„ de«      Z[ G d„ de«      Z\ G d„ d e«      Z] G d!„ d"e«      Z^d#eSd$e^fd%„Z_d&„ Z` G d'„ d(e«      Zad)eadz  d*ebdz  d$eUeb   dz  fd+„Zcd,e
eb   dz  d*ebdz  d)eadz  d$edebd-f   fd.„Ze G d/„ d0«      Zfy)1zÇ
Module responsible for

1. Writing spend increments to either in memory list of transactions or to redis
2. Reading increments from redis or in memory list of transactions and committing them to db
é    N)ÚMappingÚSequence)ÚdatetimeÚ	timedeltaÚtimezone)ÚTYPE_CHECKINGÚAnyÚFinalÚLiteralÚProtocolÚcastÚoverload)Úverbose_proxy_logger)Ú
RedisCache)Ú"DB_DAILY_TAG_SPEND_UPDATE_JOB_NAMEÚDB_SPEND_UPDATE_JOB_NAMEÚ!INTERNAL_CALL_ORIGIN_METADATA_KEY)Úcoerce_model_access_groups)Úsafe_json_loads)ÚDB_RETRY_SAFE_ERROR_TYPESÚBaseDailySpendTransactionÚDailyAgentSpendTransactionÚDailyEndUserSpendTransactionÚ!DailyOrganizationSpendTransactionÚDailyTagSpendTransactionÚDailyTeamSpendTransactionÚDailyUserSpendTransactionÚDBSpendUpdateTransactionsÚLitellm_EntityTypeÚSpendLogsMetadataÚSpendLogsPayloadÚSpendUpdateQueueItemÚToolDiscoveryQueueItem)ÚDAILY_SPEND_TABLESÚbuild_bulk_upsertÚmerge_by_conflict_key)ÚDailySpendUpdateQueue)ÚPodLockManager)ÚRedisUpdateBuffer)ÚSpendUpdateQueue)ÚToolDiscoveryQueue)ÚWindowSpendTransactionÚWindowSpendUpdateQueue)ÚROUTE_ENDPOINT_MAPPING)Ú extract_compression_saved_tokens)Úcompute_savings_spendÚextract_cache_creation_tokensÚextract_cache_read_tokensÚmarks_gateway_injection)Úspend_log_error)Ú
BatchTable)Ú	CallTypes)ÚPrismaClientÚProxyLoggingÚRESPONSES_SESSION_CALL_TYPESc                   ó^   — e Zd ZU eed<   eed<   eed<   eed<   eed<   eed<   eed<   eed<   y	)
Ú_SpendBatchÚlitellm_usertableÚlitellm_verificationtokenÚlitellm_teamtableÚlitellm_teammembershipÚlitellm_organizationtableÚlitellm_tagtableÚlitellm_agentstableÚ#litellm_modelaccessgroupbudgettableN)Ú__name__Ú
__module__Ú__qualname__r5   Ú__annotations__© ó    úl/home/oem/CyberBrain26-unified/.venv/lib/python3.12/site-packages/litellm/proxy/db/db_spend_update_writer.pyr;   r;   W   s2   … Ø!Ó!Ø)Ó)Ø!Ó!Ø&Ó&Ø)Ó)Ø Ó Ø#Ó#Ø)3Ô3rI   r;   c            	       ó6   — e Zd Zdefd„Zdededededz  fd„Zy)Ú_SpendBatchManagerÚreturnc              ƒ   ó   K  — y ­w©NrH   ©Úselfs    rJ   Ú
__aenter__z_SpendBatchManager.__aenter__c   ó   è ø� ùó   ‚Úexc_typeÚ	exc_valueÚ	tracebackNc              ƒ   ó   K  — y ­wrO   rH   ©rQ   rU   rV   rW   s       rJ   Ú	__aexit__z_SpendBatchManager.__aexit__e   rS   rT   )rD   rE   rF   r;   rR   ÚobjectÚboolrZ   rH   rI   rJ   rL   rL   b   s(   „ Ø2 +Ó2ài¨Ði¸6ÐiÈfÐiÐY]Ð`dÑYdÔirI   rL   c                   ó   — e Zd Zdefd„Zy)Ú_SpendTransactionrM   c                  ó   — y rO   rH   rP   s    rJ   Úbatch_z_SpendTransaction.batch_i   ó   � rI   N)rD   rE   rF   rL   r`   rH   rI   rJ   r^   r^   h   s   „ Ø/Ð*Ô/rI   r^   c            	       ó6   — e Zd Zdefd„Zdededededz  fd„Zy)Ú_SpendTransactionManagerrM   c              ƒ   ó   K  — y ­wrO   rH   rP   s    rJ   rR   z#_SpendTransactionManager.__aenter__m   rS   rT   rU   rV   rW   Nc              ƒ   ó   K  — y ­wrO   rH   rY   s       rJ   rZ   z"_SpendTransactionManager.__aexit__o   rS   rT   )rD   rE   rF   r^   rR   r[   r\   rZ   rH   rI   rJ   rc   rc   l   s)   „ Ø8Ð"3Ó8ài¨Ði¸6ÐiÈfÐiÐY]Ð`dÑYdÔirI   rc   Úprisma_clientrM   c                 óR   — | j                   j                  t        d¬«      ¬«      }|S )Né<   )Úseconds)Útimeout)ÚdbÚtxr   )rf   rl   s     rJ   Ú_spend_update_txrm   r   s&   € Ø*7×*:Ñ*:×*=Ñ*=ÄiÐXZÔF[Ð*=Ó*\€BØ€IrI   c                  ó2   — 	 ddl m}  | S # t        $ r Y yw xY w)zåThe proxy's router, or None outside a running proxy.

    Injected rather than imported where it is used, so the savings computation stays
    a pure function of its arguments and the caller owns where the router comes from.
    r   ©Ú
llm_routerN)Úlitellm.proxy.proxy_serverrp   Ú	Exceptionro   s    rJ   Úget_llm_routerrs   w   s"   € ðÝ9àÐøÜò Ùðús   ‚
 Š	•c                   ó,   — e Zd Zdedeeef   dz  fd„Zy)Ú_DeploymentLookupÚidrM   Nc                  ó   — y rO   rH   )rQ   rv   s     rJ   Úget_model_infoz _DeploymentLookup.get_model_info†   ra   rI   )rD   rE   rF   Ústrr   r[   rx   rH   rI   rJ   ru   ru   …   s   „ ØI ÐI¨°°f°Ñ)=ÀÑ)DÔIrI   ru   ÚrouterÚserved_model_idc                 ó   — | �|sy| j                  |¬«      }|€y|j                  d«      }t        |t        «      sy|j                  d«      }t        |t        t
        f«      s
t        «       S t        d„ |D «       «      S )zÎAccess groups declared by the deployment that actually served the request.

    None when the served deployment cannot be identified, in which case the set
    attributed at auth time stands unchanged.
    N)rv   Ú
model_infoÚaccess_groupsc              3   óB   K  — | ]  }t        |t        «      sŒ|–— Œ y ­wrO   )Ú
isinstancery   )Ú.0Úgroups     rJ   ú	<genexpr>z._served_model_access_groups.<locals>.<genexpr>�   s   è ø€ ÒK˜u´J¸uÄcÕ4J”UÑKùs   ‚˜)rx   Úgetr€   r   ÚlistÚtupleÚ	frozenset)rz   r{   Ú
deploymentr}   Údeclareds        rJ   Ú_served_model_access_groupsrŠ   ‰   sz   € ð €~™_ØØ×-Ñ-°Ð-ÓA€JØÐØØ"Ÿ™ |Ó4€JÜ�j¤'Ô*ØØ —n‘n _Ó5€HÜ�h¤¤u Ô.Ü‹{ÐÜÑK¨ÔKÓKÐKrI   Ú
attributed.c                 ój   ‡— t        | «      }|syt        ||¬«      Š‰€|S t        ˆfd„|D «       «      S )a  Groups to debit: the set attributed at auth time, narrowed to those the served model belongs to.

    The router may fall back to a model outside the pool auth reserved against, so the
    attributed set is the hard upper bound: a group absent from it is never debited.
    rH   )rz   r{   c              3   ó,   •K  — | ]  }|‰v sŒ|–— Œ y ­wrO   rH   )r�   r‚   Úserveds     €rJ   rƒ   z0debitable_model_access_groups.<locals>.<genexpr>°   s   øè ø€ Ò?˜5¨u¸ª”Ñ?ùs   ƒ	�)r   rŠ   r†   )r‹   r{   rz   ÚorderedrŽ   s       @rJ   Údebitable_model_access_groupsr�       s<   ø€ ô 0°
Ó;€GÙØÜ/°vÈÔ_€FØ€~ØˆÜÓ? GÔ?Ó?Ð?rI   c                   ó¦  — e Zd ZdZ	 dcdedz  fd„Zdedz  dedz  dedz  dedz  d	edz  d
edz  dej                  e
z  ez  dz  dedz  dedz  dedz  dedz  fd„Z	 dcdeddddd
dddf
d„Zdeddddfd„Z	 	 ddd
edz  de
dz  dedz  dedz  ddf
d„Zddœdedz  dedz  dedz  dedz  d	edz  dedz  dedz  dedz  dedee   fd„Zdedz  dedz  dedz  fd„Z	 dcdedz  dedz  dedz  dedz  dedz  f
d „Zdedz  dedz  dedz  dedz  fd!„Zdedz  d	edz  dedz  fd"„Zdedz  d#edz  dedz  fd$„Zdedz  d%edz  dedz  fd&„Z	 dcdedz  dee   dz  d'edz  dedz  d(edz  ddfd)„Zd ej>                  d*«      fdeez  dedz  d+edz  dedz  fd,„Z ded-e!d.e"fd/„Z#ded-e!d.e"fd0„Z$ded-e!d.e"fd1„Z%ded-e!d.e"fd2„Z&ded-e!d.e"fd3„Z'e(ded4ee)   ddfd5„«       Z*ded-e!d.e"ddfd6„Z+deddfd7„Z,e(d8ed9e!d-e!ded.e"ddfd:„«       Z-ded-e!d.e"d;e.fd<„Z/e(d=ed>eeef   dz  d?e0d@   dAed-e!ded.e"fdB„«       Z1e2e(d-e!ded.e"dCeee3f   dDe0dE   dFeddfdG„«       «       Z4e2e(d-e!ded.e"dCeee5f   dDe0dH   dFeddfdI„«       «       Z4e2e(d-e!ded.e"dCeee6f   dDe0dJ   dFeddfdK„«       «       Z4e2e(d-e!ded.e"dCeee7f   dDe0dL   dFeddfdM„«       «       Z4e2e(d-e!ded.e"dCeee8f   dDe0dN   dFeddfdO„«       «       Z4e2e(d-e!ded.e"dCeee9f   dDe0dP   dFeddfdQ„«       «       Z4e(d-e!ded.e"dCeee3f   eee5f   z  eee9f   z  eee6f   z  eee7f   z  eee8f   z  dDe0dR   dFeddfdS„«       Z4e(d-e!ded.e"dCeee3f   fdT„«       Z:e(d-e!ded.e"dCeee5f   fdU„«       Z;e(d-e!ded.e"dCeee6f   fdV„«       Z<e(d-e!ded.e"dCeee7f   fdW„«       Z=e(d-e!ded.e"dCeee8f   fdX„«       Z>e(d-e!ded.e"dCeee9f   fdY„«       Z?	 dedeez  dedZe0d[   de@dz  fd\„ZA	 dcdeez  dedz  fd]„ZB	 dcdededz  ddfd^„ZC	 	 dddededz  d	edz  ddfd_„ZD	 dcdededz  ddfd`„ZE	 dcdededz  ddfda„ZF	 dcdededz  ddfdb„ZGy)fÚDBSpendUpdateWriterz×
    Module responsible for

    1. Writing spend increments to either in memory list of transactions or to redis
    2. Reading increments from redis or in memory list of transactions and committing them to db
    NÚredis_cachec                 ót  — || _         t        | j                   ¬«      | _        t        «       | _        t        «       | _        t        «       | _        t        «       | _
        t        «       | _        t        «       | _        t        «       | _        t        «       | _        t        «       | _        t!        «       | _        y )N)r“   )r“   r)   Úredis_update_bufferr(   Úpod_lock_managerr*   Úspend_update_queuer+   Útool_discovery_queuer'   Údaily_spend_update_queueÚdaily_team_spend_update_queueÚ!daily_end_user_spend_update_queueÚdaily_agent_spend_update_queueÚdaily_org_spend_update_queueÚdaily_tag_spend_update_queuer-   Úwindow_spend_update_queue)rQ   r“   s     rJ   Ú__init__zDBSpendUpdateWriter.__init__»   s�   € ð 'ˆÔÜ#4À×AQÑAQÔ#RˆÔ Ü .Ó 0ˆÔÜ"2Ó"4ˆÔÜ$6Ó$8ˆÔ!Ü(=Ó(?ˆÔ%Ü-BÓ-DˆÔ*Ü1FÓ1HˆÔ.Ü.CÓ.EˆÔ+Ü,AÓ,CˆÔ)Ü,AÓ,CˆÔ)Ü)?Ó)AˆÕ&rI   ÚtokenÚuser_idÚend_user_idÚteam_idÚorg_idÚkwargsÚcompletion_responseÚ
start_timeÚend_timeÚresponse_costrM   c              ƒ   óø  K  — ddl m}m}m} ddlm}m} 	 t        j                  d|
|||«       |j                  «       du ry|�+t        |t        «      r|j                  d«      r
 ||¬«      }n|}dd	lm}m}  |||||	¬
«      }|
xs d|d<   t        |d   t         «      r|d   j#                  «       |d<   t        |d   t         «      r|d   j#                  «       |d<   |�
|dk7  r||d<   |�
|dk7  r||d<   |du rT| j%                  ||¬«      ƒ d{  –—†  | j'                  ||||¬«      ƒ d{  –—†  | j)                  ||¬«      ƒ d{  –—†  nt        j                  d«       t+        j,                  | j/                  |
|||||||| ||«      ¬«
      «       | j1                  ||||¬«       t        j                  d«       |j3                  d«      S 7 ŒÁ7 Œ¦7 Œ�# t4        $ r t7        d|
|||||«       Y yw xY w­w)zæReturns the LiteLLM_SpendLogs request_id this call was recorded
        under, so the caller can tell the budget-window writer which log rows
        its increments already cover. None when the payload could not be built.
        r   )Údisable_spend_logsÚlitellm_proxy_budget_namerf   )ÚProxyUpdateSpendÚ
hash_tokenzMEnters prisma db call, response_cost: %s, token: %s; user_id: %s; team_id: %sTNzsk-)r¡   )Úget_logging_payloadÚget_request_model_access_groups)r¦   Úresponse_objr¨   r©   ç        ÚspendÚ	startTimeÚendTimeÚ Úorganization_idr¤   F©Úpayloadrf   )rº   r§   rf   r¦   zwdisable_spend_logs=True. Skipping writing spend logs to db. Other spend updates - Key/User/Team table will still occur.)
rª   r¢   Úhashed_tokenr¤   r¥   r£   rf   r­   rº   Úrequest_model_access_groups)r¦   r§   r»   r¤   zRuns spend update on all tablesÚ
request_idzÐSpend tracking - update_database failed. Spend log insertion or daily transaction enqueue may not have completed for this request. response_cost=%s, token=%s, user_id=%s, team_id=%s, org_id=%s, end_user_id=%s)rq   r¬   r­   rf   Úlitellm.proxy.utilsr®   r¯   r   ÚdebugÚdisable_spend_updatesr€   ry   Ú
startswithÚ1litellm.proxy.spend_tracking.spend_tracking_utilsr°   r±   r   Ú	isoformatÚ_insert_spend_log_to_dbÚ_enqueue_tool_usage_transactionÚ$_enqueue_autorouter_turn_transactionÚasyncioÚcreate_taskÚ_batch_database_updatesÚ_enqueue_tool_registry_upsertr„   rr   r4   )rQ   r¡   r¢   r£   r¤   r¥   r¦   r§   r¨   r©   rª   r¬   r­   rf   r®   r¯   r»   r°   r±   rº   s                       rJ   Úupdate_databasez#DBSpendUpdateWriter.update_databaseÌ   sˆ  è ø€ ÷&	
ñ 	
÷
 	Eð`	Ü ×&Ñ&Ø_ØØØØôð  ×5Ñ5Ó7¸4Ñ?ØØÐ ¤Z°´sÔ%;À×@PÑ@PÐQVÔ@WÙ)°Ô6‘à$�÷ñ
 1ØØ0Ø%Ø!ô	ˆGð  -Ò3°ˆG�GÑÜ˜' +Ñ.´Ô9Ø'.¨{Ñ';×'EÑ'EÓ'G�˜Ñ$Ü˜' )Ñ,¬hÔ7Ø%,¨YÑ%7×%AÑ%AÓ%C�˜	Ñ"àÐ! f°¢lØ-3�Ð)Ñ*àÐ" w°"¢}Ø%,�˜	Ñ"à! UÑ*Ø×2Ñ2Ø#Ø"/ð 3ó ÷ ð ð ×:Ñ:Ø#Ø(;Ø"/Ø!ð	 ;ó ÷ ð ð ×?Ñ?Ø#Ø"/ð @ó ÷ ñ ô
 %×*Ñ*ð Nôô
 ×ÑØ×,Ñ,Ø"/Ø#Ø!-Ø#Ø!Ø +Ø"/Ø.GØ#Ù0OÐPVÓ0Wð -ó ôð ×.Ñ.ØØ$7Ø)Øð	 /ô ô !×&Ñ&Ð'HÔIØ—;‘;˜|Ó,Ð,ðWøðøðùôD ò 	Üð`ð ØØØØØô
ñ ð	üsl   ‚G:–+G ÁG:ÁCG ÄGÄG Ä/GÄ0G Å
GÅBG ÇG:ÇG ÇG ÇG ÇG7Ç4G:Ç6G7Ç7G:rº   z.litellm.ModelResponse | Any | Exception | Nonerf   zPrismaClient | Nonezdict | Nonec              ƒ   ó¼  K  — 	 |€y ddl m}  ||d   t        |d   «      |j                  d«      |d   |d   ||xs i j                  d«      ¬	«      }|€y |j                  4 ƒd {  –—†  |j
                  j                  |«       d d d «      ƒd {  –—†  y 7 Œ07 Œ# 1 ƒd {  –—†7  sw Y   y xY w# t        $ r }t        j                  d
|«       Y d }~y d }~ww xY w­w)Nr   )Úbuild_tool_usage_transactionr½   rµ   Úmcp_namespaced_tool_namer´   Útotal_tokensÚrealtime_tool_calls)r½   Ústart_time_isorÎ   r´   rÏ   r§   rÐ   z8_enqueue_tool_usage_transaction error (non-blocking): %s)
Ú%litellm.proxy.db.spend_log_tool_indexrÍ   ry   r„   Ú_tool_usage_transactions_lockÚtool_usage_transactionsÚappendrr   r   r¿   )rQ   rº   r§   rf   r¦   rÍ   ÚtransactionÚes           rJ   rÅ   z3DBSpendUpdateWriter._enqueue_tool_usage_transactionH  sô   è ø€ ð	fØÐ$Øõñ ">Ø" <Ñ0Ü" 7¨;Ñ#7Ó8Ø)0¯©Ð5OÓ)PØ˜gÑ&Ø$ ^Ñ4Ø$7Ø%+¢\¨r×$6Ñ$6Ð7LÓ$Mô"ˆKð Ð"ØØ$×BÑB÷ Jñ JØ×5Ñ5×<Ñ<¸[ÔI÷J÷ Jñ Jøð Jø÷ J÷ Jñ Jûäò 	fÜ ×&Ñ&Ð'aÐcd×eÑeûð	füs™   ‚C„B0 †C‡AB0 ÁCÁB0 Á&BÁ'B0 Á*BÂB0 ÂBÂB0 ÂCÂB0 ÂB0 ÂB-Â!B$Â"B-Â)B0 Â,CÂ-B0 Â0	CÂ9CÃCÃCÃCc              ƒ   óN  K  — 	 |€y |j                  d«      }|sy t        j                  |«      }t        |t        «      r|j                  d«      sy ddlm} |j                  d«      }t        |j                  d«      |j                  d«      dt        ||j                  d«      «      |j                  d«      t        |t        «      r|nd |j                  d«      t        |j                  d	«      |j                  d
«      ¬«
      } ||||j                  ¬«      }|€y |j                  4 ƒd {  –—†  |j                  j                  |«       d d d «      ƒd {  –—†  y 7 Œ07 Œ# 1 ƒd {  –—†7  sw Y   y xY w# t        $ r }	t        j                   d|	«       Y d }	~	y d }	~	ww xY w­w)NÚmetadataÚrouting_decisionr   )Ú!build_autorouter_turn_transactionÚusage_objectÚmodelÚcustom_llm_providerÚmodel_idÚcost_breakdownÚautorouter_savings)
rÝ   rÞ   Úcompression_saved_tokensÚgateway_injected_cacherÚ   rÜ   rß   rp   rà   Úrecorded_autorouter_savings)rº   rÙ   Úsaved_spendz=_enqueue_autorouter_turn_transaction error (non-blocking): %s)r„   ÚjsonÚloadsr€   ÚdictÚ*litellm.proxy.db.autorouter_session_rolluprÛ   r0   r3   rs   Ú
autorouterÚ"_autorouter_turn_transactions_lockÚautorouter_turn_transactionsrÕ   rr   r   r¿   )
rQ   rº   rf   Úmetadata_rawrÙ   rÛ   Úusage_object_rawÚsavings_spendrÖ   r×   s
             rJ   rÆ   z8DBSpendUpdateWriter._enqueue_autorouter_turn_transactionf  s‰  è ø€ ð
$	kØÐ$ØØ")§+¡+¨jÓ"9ˆLÙØÜ"Ÿj™j¨Ó6ˆHÜ˜h¬Ô-°X·\±\ÐBTÔ5UØõð '/§l¡l°>Ó&BÐÜ#8Ø—k‘k 'Ó*Ø$+§K¡KÐ0EÓ$FØ)*Ü'>¸xÈÏÉÐU_ÓI`Ó'aØ!)§¡Ð.@Ó!AÜ1;Ð<LÌdÔ1SÑ-ÐY]Ø Ÿ™ ZÓ0Ü)Ø'Ÿ|™|Ð,<Ó=Ø,4¯L©LÐ9MÓ,Nô$ˆMñ "CØØ!Ø)×4Ñ4ô"ˆKð
 Ð"ØØ$×GÑG÷ Oñ OØ×:Ñ:×AÑAÀ+ÔN÷O÷ Oñ Oøð Oø÷ O÷ Oñ Oûäò 	kÜ ×&Ñ&Ð'fÐhi×jÑjûð	küs¯   ‚F%„E9 †F%‡E9 šF%›6E9 ÁF%ÁCE9 ÄF%ÄE9 Ä/E Ä0E9 Ä3E$ÅE9 ÅE"ÅE9 ÅF%Å E9 Å"E9 Å$E6Å*E-Å+E6Å2E9 Å5F%Å6E9 Å9	F"ÆFÆF%ÆF"Æ"F%r»   c                 ó†  ‡ ‡‡‡‡— 	 |€ydŠ|j                  d«      xs i }|j                  d«      xs i }|j                  d«      xs dŠ|j                  d«      xs dŠddt        dt        d	dfˆˆˆ ˆˆfd
„}|j                  d«      }|�||j                  di «      xs i j                  d«      }	|	rUt        |	t        «      rE|	j                  d«      xs |	j                  d«      }
|	j                  d«      }|
r ||
|xs d¬«       |j                  d«      xs g }|D ]V  }t        |t        «      sŒ|j                  d«      xs i }t        |t        «      r|j                  d«      nd}|sŒO ||«       ŒX |j                  d«      xs i }t        |t        «      r|j                  d«      ndxs i }|j                  d«      xs g D ]/  }t        |t        «      sŒ|j                  d«      }|sŒ( ||«       Œ1 ddlm}  ||«      D ]
  }
 ||
«       Œ y# t        $ r }t        j                  d|«       Y d}~yd}~ww xY w)a˜  
        Extract tool names from the LLM request and response and enqueue them
        for upsert into LiteLLM_ToolTable via ToolDiscoveryQueue.

        Handles four sources:
        - MCP tools: standard_logging_object.mcp_tool_call_metadata.namespaced_tool_name
        - Response tool_calls (OpenAI / Anthropic pass-through converted to OpenAI format):
            completion_response.choices[].message.tool_calls[].function.name
        - Request tools array (OpenAI format): kwargs["tools"][].function.name
        - Request tools array (Anthropic /messages format): kwargs["passthrough_logging_payload"]
            ["request_body"]["tools"][].name
        NÚlitellm_paramsrÙ   Úuser_api_key_aliasÚ
user_agentÚuser_definedÚ	tool_nameÚoriginrM   c           
      óZ   •— ‰j                   j                  t        | |‰‰‰‰¬«      «       y )N)rõ   rö   Úkey_hashr¤   Ú	key_aliasró   )r˜   Ú
add_updater#   )rõ   rö   r»   rù   rQ   r¤   ró   s     €€€€€rJ   Ú_enqueuezCDBSpendUpdateWriter._enqueue_tool_registry_upsert.<locals>._enqueue¯  s1   ø€ Ø×)Ñ)×4Ñ4Ü*Ø"+Ø%Ø!-Ø 'Ø"+Ø#-ôõ	rI   Ústandard_logging_objectÚmcp_tool_call_metadataÚnamespaced_tool_nameÚnameÚmcp_server_name)rö   ÚtoolsÚfunctionÚpassthrough_logging_payloadÚrequest_bodyr   )Úresponse_tool_call_namesz6_enqueue_tool_registry_upsert error (non-blocking): %s)rô   )	r„   ry   r€   rè   rÒ   r  rr   r   r¿   )rQ   r¦   r§   r»   r¤   Ú_litellm_paramsÚ	_metadatarû   Ú	sl_objectÚmcp_metadatarõ   r   Úrequest_toolsÚtool_defÚfnrÿ   Úpassthrough_payloadr  r  r×   rù   ró   s   `  ``               @@rJ   rÊ   z1DBSpendUpdateWriter._enqueue_tool_registry_upsert‘  sH  ü€ ð&>	dØˆ~Øð %)ˆIØ%+§Z¡ZÐ0@Ó%AÒ%GÀRˆOØ.×2Ñ2°:Ó>ÒDÀ"ˆIØ!Ÿ™Ð&:Ó;ÒC¸tˆIØ )§¡¨lÓ ;Ò C¸tˆJñ
¤Cð 
´ð 
È$÷ 
ñ 
ð  &Ÿz™zÐ*CÓDˆIØÐ$Ø'0§}¡}°ZÀÓ'DÒ'JÈ×&OÑ&OÐPhÓ&i�Ù¤J¨|¼TÔ$BØ ,× 0Ñ 0Ð1GÓ HÒ dÈL×L\ÑL\Ð]cÓLd�IØ-9×-=Ñ-=Ð>OÓ-P�OÙ Ù  °?Ò3TÀnÕUð $*§:¡:¨gÓ#6Ò#<¸"ˆMØ)ò #�Ü! (¬DÔ1ØØ—\‘\ *Ó-Ò3°�Ü)3°B¼Ô)=�r—v‘v˜f”~À4�ÚÙ˜T•Nð#ð *0¯©Ð4QÓ)RÒ)XÐVXÐä;EÐFYÔ[_Ô;`Ð#×'Ñ'¨Ô7Ðfjò#àð ð )×,Ñ,¨WÓ5Ò;¸ò #�Ü! (¬DÔ1ØØ—|‘| FÓ+�ÚÙ˜T•Nð#õ Wá5Ð6IÓJò $�	Ù˜Õ#ñ$øäò 	dÜ ×&Ñ&Ð'_Ðab×cÑcûð	dús*   ‡H ŠE#H Å.BH Ç1%H È	I È H;È;I rH   )r¼   r­   r¼   c       
      ƒ   ó$	  K  — t        j                  |	«      }|j                  d«      }	 | j                  |||||¬«      ƒ d{  –—†  	 | j                  |||¬«      ƒ d{  –—†  	 | j                  ||||¬«      ƒ d{  –—†  	 | j                  |||¬	«      ƒ d{  –—†  	 | j                  |||¬«      ƒ d{  –—†  | j                  ||
|j                  d«      |t        «       ¬«      ƒ d{  –—†  |j                  d«      }	 | j                  |||¬«      ƒ d{  –—†  	 | j!                  ||¬«      ƒ d{  –—†  	 | j#                  ||¬«      ƒ d{  –—†  	 | j%                  ||¬«      ƒ d{  –—†  	 | j'                  ||¬«      ƒ d{  –—†  	 | j)                  |||¬«      ƒ d{  –—†  	 | j+                  ||¬«      ƒ d{  –—†  y7 �Œ‡# t        $ r, t        j                  dt        j                  «       «       Y �Œ¹w xY w7 �Œ¥# t        $ r, t        j                  dt        j                  «       «       Y �Œ×w xY w7 �ŒÂ# t        $ r, t        j                  dt        j                  «       «       Y �Œôw xY w7 �Œà# t        $ r, t        j                  d
t        j                  «       «       Y �Œw xY w7 �Œþ# t        $ r, t        j                  dt        j                  «       «       Y �Œ0w xY w7 �Œ7 �ŒÙ# t        $ r, t        j                  dt        j                  «       «       Y �Œw xY w7 �Œø# t        $ r, t        j                  dt        j                  «       «       Y �Œ*w xY w7 �Œ# t        $ r, t        j                  dt        j                  «       «       Y �ŒIw xY w7 �Œ6# t        $ r, t        j                  dt        j                  «       «       Y �Œhw xY w7 �ŒU# t        $ r, t        j                  dt        j                  «       «       Y �Œ‡w xY w7 �Œs# t        $ r, t        j                  dt        j                  «       «       Y �Œ¥w xY w7 �Œ’# t        $ r+ t        j                  dt        j                  «       «       Y yw xY w­w)a^  
        Runs all 13 spend-update helpers sequentially inside a single asyncio task.

        Each helper is wrapped in try/except so one failure doesn't prevent the others.

        The deepcopy runs here, off the awaited request path, so the daily spend
        helpers get a payload isolated from the spend-log queue entry and the caller.
        Úrequest_tags)rª   r¢   rf   r­   r£   Nz3_batch_database_updates: _update_user_db failed: %s)rª   r»   rf   z2_batch_database_updates: _update_key_db failed: %s)rª   r¤   r¢   rf   z3_batch_database_updates: _update_team_db failed: %s)rª   r¥   rf   z2_batch_database_updates: _update_org_db failed: %s)rª   r  rf   z2_batch_database_updates: _update_tag_db failed: %srß   )rª   r¼   r{   rf   rz   Úagent_id)rª   r  rf   z4_batch_database_updates: _update_agent_db failed: %sr¹   zW_batch_database_updates: add_spend_log_transaction_to_daily_user_transaction failed: %sz[_batch_database_updates: add_spend_log_transaction_to_daily_end_user_transaction failed: %szX_batch_database_updates: add_spend_log_transaction_to_daily_agent_transaction failed: %szW_batch_database_updates: add_spend_log_transaction_to_daily_team_transaction failed: %s)rº   r¥   rf   zV_batch_database_updates: add_spend_log_transaction_to_daily_org_transaction failed: %szV_batch_database_updates: add_spend_log_transaction_to_daily_tag_transaction failed: %s)ÚcopyÚdeepcopyr„   Ú_update_user_dbrr   r   r¿   rW   Ú
format_excÚ_update_key_dbÚ_update_team_dbÚ_update_org_dbÚ_update_tag_dbÚ_update_model_access_group_dbrs   Ú_update_agent_dbÚ3add_spend_log_transaction_to_daily_user_transactionÚ7add_spend_log_transaction_to_daily_end_user_transactionÚ4add_spend_log_transaction_to_daily_agent_transactionÚ3add_spend_log_transaction_to_daily_team_transactionÚ2add_spend_log_transaction_to_daily_org_transactionÚ2add_spend_log_transaction_to_daily_tag_transaction)rQ   rª   r¢   r»   r¤   r¥   r£   rf   r­   rº   r¼   Úpayload_copyr  Ú_agent_id_for_spends                 rJ   rÉ   z+DBSpendUpdateWriter._batch_database_updatesä  sã  è ø€ ô, #Ÿm™m¨GÓ4ˆØ*×.Ñ.¨~Ó>ˆð	Ø×&Ñ&Ø+ØØ+Ø*CØ'ð 'ó ÷ ð ð
	Ø×%Ñ%Ø+Ø)Ø+ð &ó ÷ ð ð	Ø×&Ñ&Ø+ØØØ+ð	 'ó ÷ ð ð
	Ø×%Ñ%Ø+ØØ+ð &ó ÷ ð ð
	Ø×%Ñ%Ø+Ø)Ø+ð &ó ÷ ð ð ×0Ñ0Ø'Ø(CØ(×,Ñ,¨ZÓ8Ø'Ü!Ó#ð 1ó 
÷ 	
ð 	
ð &2×%5Ñ%5°jÓ%AÐð
	Ø×'Ñ'Ø+Ø,Ø+ð (ó ÷ ð ð		Ø×JÑJØ$Ø+ð Kó ÷ ð ð		Ø×NÑNØ$Ø+ð Oó ÷ ð ð		Ø×KÑKØ$Ø+ð Ló ÷ ð ð		Ø×JÑJØ$Ø+ð Kó ÷ ð ð
	Ø×IÑIØ$ØØ+ð Jó ÷ ð ð		Ø×IÑIØ$Ø+ð Jó ÷ ñ ðYúô ò 	Ü ×&Ñ&ØEÜ×$Ñ$Ó&÷ð	úðúô
 ò 	Ü ×&Ñ&ØDÜ×$Ñ$Ó&÷ð	úðúô ò 	Ü ×&Ñ&ØEÜ×$Ñ$Ó&÷ð	úðúô
 ò 	Ü ×&Ñ&ØDÜ×$Ñ$Ó&÷ð	úðúô
 ò 	Ü ×&Ñ&ØDÜ×$Ñ$Ó&÷ð	úð	
ùðúô
 ò 	Ü ×&Ñ&ØFÜ×$Ñ$Ó&÷ð	úðúô ò 	Ü ×&Ñ&ØiÜ×$Ñ$Ó&÷ð	úðúô ò 	Ü ×&Ñ&ØmÜ×$Ñ$Ó&÷ð	úðúô ò 	Ü ×&Ñ&ØjÜ×$Ñ$Ó&÷ð	úðúô ò 	Ü ×&Ñ&ØiÜ×$Ñ$Ó&÷ð	úðúô
 ò 	Ü ×&Ñ&ØhÜ×$Ñ$Ó&÷ð	úðúô ò 	Ü ×&Ñ&ØhÜ×$Ñ$Ó&öð	üs\  ‚'RªG ÁG
ÁG Á	H Á HÁ!H Á&I Á>I Á?I ÂI> ÂI;ÂI> Â!J9 Â8J6Â9J9 Â=0RÃ-K1Ã.RÄK7 ÄK4ÄK7 Ä!L2 Ä7L/Ä8L2 Ä=M- ÅM*ÅM- ÅN( Å/N%Å0N( Å5O# ÆO ÆO# ÆP Æ(PÆ)P Æ.Q ÇQÇQ Ç	RÇ
G Ç1HÇ>RÈHÈRÈH È1H=È9RÈ<H=È=RÉ I É1I8É4RÉ7I8É8RÉ;I> É>1J3Ê/RÊ2J3Ê3RÊ6J9 Ê91K.Ë*RË-K.Ë.RË4K7 Ë71L,Ì(RÌ+L,Ì,RÌ/L2 Ì21M'Í#RÍ&M'Í'RÍ*M- Í-1N"ÎRÎ!N"Î"RÎ%N( Î(1OÏRÏOÏRÏ O# Ï#1PÐRÐPÐRÐP Ð1QÑRÑQÑRÑQ Ñ1RÒ
RÒRÒRc              ƒ   óì   K  — 	 |�|€y | j                   j                  t        t        j                  ||¬«      ¬«      ƒ d {  –—†  y 7 Œ# t
        $ r}t        dt        |«      |¬«       |‚d }~ww xY w­w)N©Úentity_typeÚ	entity_idrª   ©Úupdatez)Update Key DB Call failed to execute - %s©Úexc)r—   rú   r"   r   ÚKEYrr   r4   ry   )rQ   rª   r»   rf   r×   s        rJ   r  z"DBSpendUpdateWriter._update_key_db“  s{   è ø€ ð	ØÐ# }Ð'<Øà×)Ñ)×4Ñ4Ü+Ü 2× 6Ñ 6Ø*Ø"/ôð 5ó ÷ ò ùô ò 	ÜÐGÌÈQËÐUVÕWØˆGûð	üsD   ‚A4„A
 ˆA4‰9A
 ÁAÁA
 ÁA4ÁA
 Á
	A1ÁA,Á,A1Á1A4c           
   ƒ   óÜ  K  — 	 |�±|g}t         j                  dkD  r|j                  |«       |D ]C  }|€Œ| j                  j	                  t        t        j                  ||¬«      ¬«      ƒ d{  –—†  ŒE |�?| j                  j	                  t        t        j                  ||¬«      ¬«      ƒ d{  –—†  yyy7 ŒI7 Œ	# t        $ r$}t        d|||t        |«      |¬«       Y d}~yd}~ww xY w­w)zi
        - Update that user's row
        - Update litellm-proxy-budget row (global proxy spend)
        Nr   r$  r'  zgSpend tracking - failed to enqueue user spend update. user_id=%s, end_user_id=%s, response_cost=%s - %sr)  )ÚlitellmÚ
max_budgetrÕ   r—   rú   r"   r   ÚUSERÚEND_USERrr   r4   ry   )	rQ   rª   r¢   rf   r­   r£   Úuser_idsÚ_idr×   s	            rJ   r  z#DBSpendUpdateWriter._update_user_db¨  s  è ø€ ð!	ØÐ(Ø#* )�Ü×%Ñ%¨Ò)Ø—O‘OÐ$=Ô>à#ò �CØ‘Ø"×5Ñ5×@Ñ@Ü#7Ü,>×,CÑ,CØ*-Ø.;ô$ð Aó ÷ ñ ðð Ð*Ø×1Ñ1×<Ñ<Ü3Ü(:×(CÑ(CØ&1Ø*7ô ð =ó ÷ ñ ð +ð )ðøðùô ò 		ÜðDàØØÜ�A“Ø÷ò ûð		üsX   ‚C,„0B< µ9B< Á.B8Á/AB< Â0B:Â1B< Â5C,Â8B< Â:B< Â<	C)ÃC$ÃC,Ã$C)Ã)C,c           
   ƒ   ó  K  — 	 |�|€t        j                  d«       y | j                  j                  t	        t
        j                  ||¬«      ¬«      ƒ d {  –—†  	 |�Gd|› d|› �}| j                  j                  t	        t
        j                  ||¬«      ¬«      ƒ d {  –—†  y y 7 ŒO7 Œ# t        $ r$}t        d|||t        |«      |¬«       Y d }~y d }~ww xY w# t        $ r }t        d||t        |«      |¬«       |‚d }~ww xY w­w)	NzZtrack_cost_callback: team_id is None or prisma_client is None. Not tracking spend for teamr$  r'  z	team_id::z::user_id::zjSpend tracking - failed to enqueue team member spend update. team_id=%s, user_id=%s, response_cost=%s - %sr)  zWSpend tracking - failed to enqueue team spend update. team_id=%s, response_cost=%s - %s)r   r¿   r—   rú   r"   r   ÚTEAMÚTEAM_MEMBERrr   r4   ry   )rQ   rª   r¤   r¢   rf   Úteam_member_keyr×   s          rJ   r  z#DBSpendUpdateWriter._update_team_db×  s6  è ø€ ð-	Øˆ -Ð"7Ü$×*Ñ*Øpôð à×)Ñ)×4Ñ4Ü+Ü 2× 7Ñ 7Ø%Ø"/ôð 5ó ÷ ð ðàÐ&à/8¸¸	ÀÈWÈIÐ-V�OØ×1Ñ1×<Ñ<Ü3Ü(:×(FÑ(FØ&5Ø*7ô ð =ó ÷ ñ ð 'ðøðùô ò 	ÜðDàØØ!Ü˜“FØ÷ò ûð	ûô ò 	ÜØiØØÜ�A“Øõð ˆGûð	üs�   ‚D„C �Dž9C ÁB'ÁC ÁAB+ Â B)Â!B+ Â%DÂ'C Â)B+ Â+	CÂ4CÃC ÃDÃCÃC Ã	DÃ$C?Ã?DÄDc           	   ƒ   ó  K  — 	 |�|€t        j                  d«       y | j                  j                  t	        t
        j                  ||¬«      ¬«      ƒ d {  –—†  y 7 Œ# t        $ r }t        d||t        |«      |¬«       |‚d }~ww xY w­w)NzXtrack_cost_callback: org_id is None or prisma_client is None. Not tracking spend for orgr$  r'  zUSpend tracking - failed to enqueue org spend update. org_id=%s, response_cost=%s - %sr)  )
r   r¿   r—   rú   r"   r   ÚORGANIZATIONrr   r4   ry   )rQ   rª   r¥   rf   r×   s        rJ   r  z"DBSpendUpdateWriter._update_org_db  s˜   è ø€ ð	Øˆ~ Ð!6Ü$×*Ñ*Ønôð à×)Ñ)×4Ñ4Ü+Ü 2× ?Ñ ?Ø$Ø"/ôð 5ó ÷ ò ùô ò 	ÜØgØØÜ�A“Øõð ˆGûð	üsD   ‚B„A �Bž9A ÁAÁA ÁBÁA Á	BÁ(BÂBÂBr  c           	   ƒ   óð   K  — 	 |�|€y | j                   j                  t        t        j                  ||¬«      ¬«      ƒ d {  –—†  y 7 Œ# t
        $ r }t        d||t        |«      |¬«       |‚d }~ww xY w­w)Nr$  r'  zYSpend tracking - failed to enqueue agent spend update. agent_id=%s, response_cost=%s - %sr)  )r—   rú   r"   r   ÚAGENTrr   r4   ry   )rQ   rª   r  rf   r×   s        rJ   r  z$DBSpendUpdateWriter._update_agent_db+  s†   è ø€ ð	ØÐ =Ð#8Øà×)Ñ)×4Ñ4Ü+Ü 2× 8Ñ 8Ø&Ø"/ôð 5ó ÷ ò ùô ò 	ÜØkØØÜ�A“Øõð ˆGûð	üsD   ‚A6„A
 ˆA6‰9A
 ÁAÁA
 ÁA6ÁA
 Á
	A3ÁA.Á.A3Á3A6r  c           	   ƒ   ó¾  K  — 	 |�|€yg }t        |t        «      r&t        |g ¬«      }|s+t        j                  d|«       yt        |t
        «      r|}ny|D ]T  }|sŒt        |t        «      sŒ| j                  j                  t        t        j                  ||¬«      ¬«      ƒ d{  –—†  ŒV y7 Œ# t        $ r }t        d||t        |«      |¬«       |‚d}~ww xY w­w)zþ
        Update spend for all tags in the request.

        Args:
            response_cost: Cost of the request
            request_tags: JSON string of tags list e.g. '["prod-tag", "test-tag"]'
            prisma_client: Prisma client instance
        N)Údefaultz%Failed to parse request_tags JSON: %sr$  r'  z[Spend tracking - failed to enqueue tag spend update. request_tags=%s, response_cost=%s - %sr)  )r€   ry   r   r   r¿   r…   r—   rú   r"   r   ÚTAGrr   r4   )rQ   rª   r  rf   ÚtagsÚtag_namer×   s          rJ   r  z"DBSpendUpdateWriter._update_tag_dbF  sï   è ø€ ð"	ØÐ# }Ð'<Øð ˆDÜ˜,¬Ô,Ü& |¸RÔ@�ÙÜ(×.Ñ.Ð/VÐXdÔeØÜ˜L¬$Ô/Ø#‘àð !ò �Ú¤
¨8´SÕ 9Ø×1Ñ1×<Ñ<Ü3Ü(:×(>Ñ(>Ø&.Ø*7ô ð =ó ÷ ñ ñðùô ò 	ÜØmØØÜ�A“Øõð ˆGûð	üsh   ‚C„B1 ˆC‰7B1 Á CÁB1 ÁCÁB1 ÁB1 Á.9B1 Â'B/Â(B1 Â.CÂ/B1 Â1	CÂ:CÃCÃCr{   rz   c           	   ƒ   ó  K  — 	 |€yt        |||¬«      D ]@  }| j                  j                  t        t        j
                  ||¬«      ¬«      ƒ d{  –—†  ŒB y7 Œ# t        $ r#}t        d||t        |«      |¬«       Y d}~yd}~ww xY w­w)a	  
        Update spend for every model access group this request is billed against.

        Args:
            response_cost: Cost of the request, charged in full to each group
            request_model_access_groups: Groups attributed at auth time, the upper bound on what may be debited
            served_model_id: Deployment id actually served, used to narrow the attributed set
            prisma_client: Prisma client instance
            router: Deployment lookup used to re-resolve groups after a fallback
        N)r‹   r{   rz   r$  r'  zqSpend tracking - failed to enqueue model access group spend update. model_access_groups=%s, response_cost=%s - %sr)  )	r�   r—   rú   r"   r   ÚMODEL_ACCESS_GROUPrr   r4   ry   )rQ   rª   r¼   r{   rf   rz   Úmodel_access_groupr×   s           rJ   r  z1DBSpendUpdateWriter._update_model_access_group_dbx  s§   è ø€ ð$	ØÐ$Øä&CØ6Ø /Øô'ò Ð"ð
 ×-Ñ-×8Ñ8Ü/Ü$6×$IÑ$IØ"4Ø&3ôð 9ó ÷ ñ ñð
ùô ò 	Üð@à+ØÜ�A“Ø÷ò ûð	üsK   ‚B
„A †B
‡A
A ÁAÁA ÁB
ÁA Á	BÁ$BÁ=B
ÂBÂB
ÚSPEND_LOGS_URLÚspend_logs_urlc              ƒ   óB  K  — t        j                  dj                  |j                  d«      |j                  d«      «      «       |�|€|�:ddlm}m}  |||f«      ƒ d {  –—†  |j                  d«      t        v r |«        |S t        j                  d«       |S 7 Œ;­w)Nz3Writing spend log to db - request_id: {}, spend: {}r½   r´   r   )Úenqueue_spend_logsÚrequest_spend_log_flushÚ	call_typeú9prisma_client is None. Skipping writing spend logs to db.)r   r¿   Úformatr„   r¾   rF  rG  r9   )rQ   rº   rf   rD  rF  rG  s         rJ   rÄ   z+DBSpendUpdateWriter._insert_spend_log_to_db¤  sŸ   è ø€ ô 	×"Ñ"ØA×HÑHØ—‘˜LÓ)¨7¯;©;°wÓ+?óô	
ð
 Ð$¨Ð)CÀ}ÐG`ßWá$ ]°W°JÓ?×?Ð?Ø�{‰{˜;Ó'Ô+GÑGÙ'Ô)ð Ðô !×&Ñ&Ð'bÔcàÐð @ús   ‚ABÁ!BÁ"<BÚn_retry_timesÚproxy_logging_objc              ƒ   ó®   K  — t        j                  «       r| j                  |||¬«      ƒ d{  –—†  y| j                  |||¬«      ƒ d{  –—†  y7 Œ"7 Œ­w)a=  
        Handles commiting update spend transactions to db

        `UPDATES` can lead to deadlocks, hence we handle them separately

        Args:
            prisma_client: PrismaClient object
            n_retry_times: int, number of retry times
            proxy_logging_obj: ProxyLogging object

        How this works:
        - Check `general_settings.use_redis_transaction_buffer`
            - If enabled, write in-memory transactions to Redis
            - Check if this Pod should read from the DB
        else:
            - Regular flow of this method
        ©rf   rK  rL  N)r)   Ú%_should_commit_spend_updates_to_redisÚ&_commit_spend_updates_to_db_with_redisÚ0_commit_spend_updates_to_db_without_redis_buffer)rQ   rf   rK  rL  s       rJ   Ú#db_update_spend_transaction_handlerz7DBSpendUpdateWriter.db_update_spend_transaction_handlerº  sn   è ø€ ô. ×BÑBÔDØ×=Ñ=Ø+Ø+Ø"3ð >ó ÷ ñ ð ×GÑGØ+Ø+Ø"3ð Hó ÷ ñ ðøðús!   ‚,A®A¯AÁAÁAÁAc              ƒ   óz	  K  — | j                   j                  | j                  | j                  | j                  | j
                  | j                  | j                  | j                  ¬«      ƒ d{  –—†  | j                  j                  t        ¬«      ƒ d{  –—† �rIt        j                  d«       i }	 | j                   j                  «       ƒ d{  –—† \  }}}}}	}
}|||||	|
|dœ}|��7t        j                  dt!        |j#                  d«      xs i «      t!        |j#                  d«      xs i «      t!        |j#                  d	«      xs i «      t!        |j#                  d
«      xs i «      t!        |j#                  d«      xs i «      t!        |j#                  d«      xs i «      t!        |j#                  d«      xs i «      t!        |j#                  d«      xs i «      t!        |j#                  d«      xs i «      «
       | j%                  ||||¬«      ƒ d{  –—†  |j'                  dd«       |�!t(        j+                  ||||¬«      ƒ d{  –—†  |j'                  dd«       |�!t(        j-                  ||||¬«      ƒ d{  –—†  |j'                  dd«       |�!t(        j/                  ||||¬«      ƒ d{  –—†  |j'                  dd«       |	�!t(        j1                  ||||	¬«      ƒ d{  –—†  |j'                  dd«       |
�!t(        j3                  ||||
¬«      ƒ d{  –—†  |j'                  dd«       |�t(        j5                  ||¬«      ƒ d{  –—†  |j'                  dd«       |j=                  «       D ��ci c]  \  }}|€Œ	||“Œ }}}|r$ | j                   j>                  di |¤Žƒ d{  –—†  | j                  jA                  t        ¬«      ƒ d{  –—†  yy7 �Œx7 �ŒS7 �Œ7 �ŒÒ7 �Œ 7 �Œn7 �Œ<7 �Œ
7 Œ×7 Œ¦# t6        $ r!}t9        dt;        |«      |¬«       Y d}~Œ·d}~ww xY wc c}}w 7 Œ}7 ŒW# |j=                  «       D ��ci c]  \  }}|€Œ	||“Œ nc c}}w }}}|r% | j                   j>                  di |¤Žƒ d{  –—†7   | j                  jA                  t        ¬«      ƒ d{  –—†7   w xY w­w)a¨  
        Handler to commit spend updates to Redis and attempt to acquire lock to commit to db

        This is a v2 scalable approach to first commit spend updates to redis, then commit to db

        This minimizes DB Deadlocks since
            - All pods only need to write their spend updates to redis
            - Only 1 pod will commit to db at a time (based on if it can acquire the lock over writing to DB)
        )r—   r™   rš   r�   r›   rœ   rŸ   N©Ú
cronjob_idzacquired lock for spend updates)Údb_spend_update_transactionsÚdaily_spend_update_transactionsÚ$daily_team_spend_update_transactionsÚ#daily_org_spend_update_transactionsÚ(daily_end_user_spend_update_transactionsÚ%daily_agent_spend_update_transactionsÚ window_spend_update_transactionsz«Spend tracking - committing spend updates from Redis to DB: keys=%d, users=%d, teams=%d, orgs=%d, end_users=%d, team_members=%d, tags=%d, agents=%d, model_access_groups=%dÚkey_list_transactionsÚuser_list_transactionsÚteam_list_transactionsÚorg_list_transactionsÚend_user_list_transactionsÚteam_member_list_transactionsÚtag_list_transactionsÚagent_list_transactionsÚ$model_access_group_list_transactions©rf   rK  rL  rV  rV  ©rK  rf   rL  Údaily_spend_transactionsrW  rX  rY  rZ  r[  ©rf   Úwindow_spend_transactionsr\  z�Spend tracking - failed to commit spend updates from Redis to DB. Re-queuing uncommitted transactions to Redis for retry on next tick. Error: %sr)  rH   )!r•   Ú&store_in_memory_spend_updates_in_redisr—   r™   rš   r�   r›   rœ   rŸ   r–   Úacquire_lockr   r   r¿   Ú/get_all_transactions_from_redis_buffer_pipelineÚinfoÚlenr„   Ú_commit_spend_updates_to_dbÚpopr’   Úupdate_daily_user_spendÚupdate_daily_team_spendÚupdate_daily_org_spendÚupdate_daily_end_user_spendÚupdate_daily_agent_spendÚ_commit_window_spend_updatesrr   r4   ry   ÚitemsÚrestore_transactions_to_redisÚrelease_lock)rQ   rf   rK  rL  ÚuncommittedrV  rW  rX  rY  rZ  r[  r\  r×   rÿ   ÚtxnsÚ
to_restores                   rJ   rP  z:DBSpendUpdateWriter._commit_spend_updates_to_db_with_redisß  sL  è ø€ ð ×&Ñ&×MÑMØ#×6Ñ6Ø%)×%BÑ%BØ*.×*LÑ*LØ)-×)JÑ)JØ.2×.TÑ.TØ+/×+NÑ+NØ&*×&DÑ&Dð Nó 
÷ 	
ð 	
ð ×&Ñ&×3Ñ3Ü/ð 4ó 
÷ 
ñ 
ô !×&Ñ&Ð'HÔIà*,ˆKðmð ×2Ñ2×bÑbÓd×dñØ0Ø3Ø8Ø7Ø<Ø9Ø4ð 5QØ7VØ<`Ø;^Ø@hØ=bØ8Xñ�ð 0Ñ;Ü(×-Ñ-ð1ô Ð8×<Ñ<Ð=TÓUÒ[ÐY[Ó\ÜÐ8×<Ñ<Ð=UÓVÒ\ÐZ\Ó]ÜÐ8×<Ñ<Ð=UÓVÒ\ÐZ\Ó]ÜÐ8×<Ñ<Ð=TÓUÒ[ÐY[Ó\ÜÐ8×<Ñ<Ð=YÓZÒ`Ð^`ÓaÜÐ8×<Ñ<Ð=\Ó]ÒcÐacÓdÜÐ8×<Ñ<Ð=TÓUÒ[ÐY[Ó\ÜÐ8×<Ñ<Ð=VÓWÒ]Ð[]Ó^ÜÐ8×<Ñ<Ð=cÓdÒjÐhjÓkôð ×:Ñ:Ø&3Ø&3Ø*;Ø5Qð	 ;ó ÷ ð ð —‘Ð >ÀÔEà2Ð>Ü-×EÑEØ&3Ø&3Ø*;Ø1Pð	 Fó ÷ ð ð —‘Ð AÀ4ÔHà7ÐCÜ-×EÑEØ&3Ø&3Ø*;Ø1Uð	 Fó ÷ ð ð —‘Ð FÈÔMà6ÐBÜ-×DÑDØ&3Ø&3Ø*;Ø1Tð	 Eó ÷ ð ð —‘Ð EÀtÔLà;ÐGÜ-×IÑIØ&3Ø&3Ø*;Ø1Yð	 Jó ÷ ð ð —‘Ð JÈDÔQà8ÐDÜ-×FÑFØ&3Ø&3Ø*;Ø1Vð	 Gó ÷ ð ð —‘Ð GÈÔNØ3Ð?Ü-×JÑJØ&3Ø2Rð Kó ÷ ð ð —‘Ð BÀDÔIð 2=×1BÑ1BÓ1D÷Ù#- 4¨ÈÑHX�D˜$‘Jð�
ñ ñ ØP˜$×2Ñ2×PÑPÑ^ÐS]Ñ^×^Ð^Ø×+Ñ+×8Ñ8Ü7ð 9ó ÷ ñ ðe
ð	
ùð
ùð  eùð6ùðùðùðùðùðøðùô
 ò Üðeä˜“FØ÷	ò ûðüóð _øðùð	 2=×1BÑ1BÓ1D÷Ù#- 4¨ÈÑHX�D˜$‘Jñùó �
ñ ñ ØP˜$×2Ñ2×PÑPÑ^ÐS]Ñ^×^Ñ^Ø×+Ñ+×8Ñ8Ü7ð 9ó ÷ ò üsK  ‚A,R;Á.O&Á/'R;ÂO)ÂR;Â4P ÃO,ÃEP ÈO/È4P ÉO2É4P ÊO5Ê4P Ê<O8Ê=4P Ë1O;Ë24P Ì&O>Ì'2P ÍP ÍP Í0R;Î
P/ÎP/Î$R;Î7P5Î8'R;ÏP7Ï R;Ï)R;Ï,P Ï/P Ï2P Ï5P Ï8P Ï;P Ï>P Ð P Ð	P,ÐP'Ð"P9 Ð'P,Ð,P9 Ð/R;Ð7R;Ð9R8Ñ
Q
ÑQ
Ñ+R8ÒRÒ	(R8Ò1R4Ò2R8Ò8R;c              ƒ   ó  K  — | j                   j                  «       ƒ d{  –—† }| j                  ||||¬«      ƒ d{  –—†  t        t        t
        t        f   | j                  j                  «       ƒ d{  –—† «      }t        j                  ||||¬«      ƒ d{  –—†  t        t        t
        t        f   | j                  j                  «       ƒ d{  –—† «      }t        j                  ||||¬«      ƒ d{  –—†  t        t        t
        t        f   | j                  j                  «       ƒ d{  –—† «      }t        j!                  ||||¬«      ƒ d{  –—†  t        t        t
        t"        f   | j$                  j                  «       ƒ d{  –—† «      }t        j'                  ||||¬«      ƒ d{  –—†  t        t        t
        t(        f   | j*                  j                  «       ƒ d{  –—† «      }	t        j-                  ||||	¬«      ƒ d{  –—†  | j.                  j1                  «       ƒ d{  –—† }
	 t        j3                  ||
¬«      ƒ d{  –—†  | j?                  |¬«      ƒ d{  –—†  y7 �ŒU7 �Œ;7 �Œ7 �Œã7 �Œ­7 �Œ‹7 �ŒU7 �Œ37 Œü7 ŒÙ7 Œ¢7 Œ7 Œ_7 ŒA# t4        $ rY}t7        dt9        |
«      t        |«      |¬«       | j.                  j:                  j=                  |
«      ƒ d{  –—†7   Y d}~Œœd}~ww xY w7 ŒŽ­w)a4  
        Commits all the spend `UPDATE` transactions to the Database

        This is the regular flow of committing to db without using a redis buffer

        Note: This flow causes Deadlocks in production (1K RPS+). Use self._commit_spend_updates_to_db_with_redis() instead if you expect 1K+ RPS.
        Nrf  rg  ri  zSpend tracking - failed to commit budget window spend updates. Re-queued %d window increments for retry on next tick. Error: %sr)  )rf   ) r—   Ú5flush_and_get_aggregated_db_spend_update_transactionsrp  r   rè   ry   r   r™   Ú8flush_and_get_aggregated_daily_spend_update_transactionsr’   rr  r   rš   rs  r   r�   rt  r   r›   ru  r   rœ   rv  rŸ   Ú2flush_and_get_aggregated_window_spend_transactionsrw  rr   r4   ro  Úupdate_queueÚputÚ_flush_tool_discovery_queue)rQ   rf   rK  rL  rV  rW  rX  rY  rZ  r[  r\  r×   s               rJ   rQ  zDDBSpendUpdateWriter._commit_spend_updates_to_db_without_redis_buffero  s,  è ø€ ð" ×)Ñ)×_Ñ_Óa×að 	%ð ×.Ñ.Ø'Ø'Ø/Ø)Eð	 /ó 
÷ 	
ð 	
ô 26Ü”Ô/Ð/Ñ0Ø×/Ñ/×hÑhÓj×jó2
Ð'ô
 "×9Ñ9Ø'Ø'Ø/Ø%Dð	 :ó 
÷ 	
ð 	
ô 7;Ü”Ô/Ð/Ñ0Ø×4Ñ4×mÑmÓo×oó7
Ð,ô
 "×9Ñ9Ø'Ø'Ø/Ø%Ið	 :ó 
÷ 	
ð 	
ô 6:Ü”Ô7Ð7Ñ8Ø×3Ñ3×lÑlÓn×nó6
Ð+ô
 "×8Ñ8Ø'Ø'Ø/Ø%Hð	 9ó 
÷ 	
ð 	
ô ;?Ü”Ô2Ð2Ñ3Ø×8Ñ8×qÑqÓs×só;
Ð0ô
 "×=Ñ=Ø'Ø'Ø/Ø%Mð	 >ó 
÷ 	
ð 	
ô 8<Ü”Ô0Ð0Ñ1Ø×5Ñ5×nÑnÓp×pó8
Ð-ô
 "×:Ñ:Ø'Ø'Ø/Ø%Jð	 ;ó 
÷ 	
ð 	
ð ×0Ñ0×cÑcÓe×eð 	)ð	dÜ%×BÑBØ+Ø*Jð Có ÷ ð ð ×.Ñ.¸]Ð.ÓK×KÑKðO bùð	
ùð kùð	
ùð pùð	
ùð oùð	
ùð tøð	
øð qøð	
øð føðùô ò 	dÜðSäÐ4Ó5Ü�A“Øõð ×0Ñ0×=Ñ=×AÑAÐBbÓc×cÖcûð	dúð 	Lús:  ‚L  I5¡L ½I8¾8L Á6I;
Á7$L ÂI>Â8L ÃJ
Ã$L Ã9JÃ:8L Ä2J
Ä3$L ÅJ
Å8L ÆJ
Æ$L Æ5JÆ68L Ç.J
Ç/$L ÈJÈ!L È5JÈ6L È;J ÉJÉJ ÉL É/K>É0L É8L É;L É>L ÊL ÊL ÊL Ê
L ÊL ÊL ÊL ÊL ÊL ÊJ Ê	K;Ê"A	K6Ë+K.Ë,K6Ë1L Ë6K;Ë;L c              ƒ   óÖ   K  — t        t        t        t        f   | j                  j                  «       ƒ d{  –—† «      }|r"t        j                  ||||¬«      ƒ d{  –—†  yy7 Œ-7 Œ­w)z…
        Commit only tag spend updates to database.
        This is called by a separate scheduler job at a longer interval.
        Nrg  )r   rè   ry   r   rž   r€  r’   Úupdate_daily_tag_spend©rQ   rf   rK  rL  Ú#daily_tag_spend_update_transactionss        rJ   Ú_commit_daily_tag_spend_to_dbz1DBSpendUpdateWriter._commit_daily_tag_spend_to_dbé  su   è ø€ ô 6:Ü”Ô.Ð.Ñ/Ø×3Ñ3×lÑlÓn×nó6
Ð+ñ
 /Ü%×<Ñ<Ø+Ø+Ø"3Ø)Lð	 =ó ÷ ñ ð /ð oøðús!   ‚5A)·A%
¸&A)ÁA'ÁA)Á'A)c              ƒ   ó4  K  — | j                   j                  | j                  ¬«      ƒ d{  –—†  | j                  j	                  t
        ¬«      ƒ d{  –—† r[t        j                  d«       	 | j                  |||¬«      ƒ d{  –—†  | j                  j                  t
        ¬«      ƒ d{  –—†  yy7 Œˆ7 Œb7 Œ2# t        $ r!}t        dt        |«      |¬«       Y d}~ŒUd}~ww xY w7 Œ9# | j                  j                  t
        ¬«      ƒ d{  –—†7   w xY w­w)z¼
        Commit daily tag spend updates using Redis buffering.

        This lets the dedicated daily tag scheduler drain both in-memory and
        Redis-backed tag transactions.
        )rž   NrT  z)acquired lock for daily tag spend updatesrN  z�Spend tracking - failed to commit daily tag spend updates from Redis to DB. Re-queuing to Redis for retry on next tick. Error: %sr)  )r•   Ú0store_in_memory_daily_tag_spend_updates_in_redisrž   r–   rl  r   r   r¿   Ú,_drain_and_commit_daily_tag_spend_from_redisrr   r4   ry   rz  )rQ   rf   rK  rL  r×   s        rJ   Ú(_commit_daily_tag_spend_to_db_with_redisz<DBSpendUpdateWriter._commit_daily_tag_spend_to_db_with_redis   s2  è ø€ ð ×&Ñ&×WÑWØ)-×)JÑ)Jð Xó 
÷ 	
ð 	
ð ×&Ñ&×3Ñ3Ü9ð 4ó 
÷ 
ð 
ô !×&Ñ&Ð'RÔSðØ×GÑGØ"/Ø"/Ø&7ð Hó ÷ ð ð ×+Ñ+×8Ñ8ÜAð 9ó ÷ ñ ð%
ð		
øð
øð
ùô
 ò ÜðLä˜“FØ÷	ò ûðúðù�d×+Ñ+×8Ñ8ÜAð 9ó ÷ ò üs‡   ‚*D¬B5­'DÁB7ÁDÁ/B; ÂB9ÂB; Â#DÂ.C(Â/DÂ7DÂ9B; Â;	C%ÃC ÃC* Ã C%Ã%C* Ã(DÃ*$DÄDÄDÄDrj  c              ƒ   ó@   K  — ddl m}  || |¬«      ƒ d{  –—†  y7 Œ­w)au  
        Commit per-budget-window spend increments to LiteLLM_BudgetWindowSpend.

        Raises on failure so the caller re-queues the increments: budget
        enforcement trusts a current row without reconciling it against
        LiteLLM_SpendLogs, so a dropped increment would let the entity spend
        past its window limit after the next counter reseed.
        r   )Úcommit_window_spend_updates)rf   ÚtransactionsN)Ú+litellm.proxy.db.budget_window_spend_writerr�  )rf   rj  r�  s      rJ   rw  z0DBSpendUpdateWriter._commit_window_spend_updates&  s%   è ø€ õ	
ñ *Ø'Ø2ô
÷ 	
ò 	
ús   ‚–—c              ƒ   ó  K  — | j                   j                  «       ƒ d{  –—† }|sy	 t        j                  ||||¬«      ƒ d{  –—†  y7 Œ*7 Œ# t        $ r' | j                   j                  |¬«      ƒ d{  –—†7   ‚ w xY w­w)a  
        Drain the Redis tag spend buffer and commit it, restoring the drained transactions if the commit fails.

        The drain is destructive, so a failed commit must push the transactions back for the next tick
        or their spend is lost permanently.
        Nrg  )rˆ  )r•   Ú=get_all_daily_tag_spend_update_transactions_from_redis_bufferr’   r†  rr   ry  r‡  s        rJ   rŒ  z@DBSpendUpdateWriter._drain_and_commit_daily_tag_spend_from_redis<  s    è ø€ ð ×*Ñ*×hÑhÓj×jð 	,ñ 3Øð	Ü%×<Ñ<Ø+Ø+Ø"3Ø)Lð	 =ó ÷ ñ ð køðùô ò 	Ø×*Ñ*×HÑHØ4Wð Ió ÷ ñ ð ð		üsD   ‚B A¡B©A ÁAÁA Á
BÁA Á(A?Á7A:Á8A?Á?Bc              ƒ   óÔ   K  — ddl m} 	 | j                  j                  «       }|r |||¬«      ƒ d{  –—†  yy7 Œ# t        $ r }t        j                  d|«       Y d}~yd}~ww xY w­w)zKFlush ToolDiscoveryQueue and batch-upsert new tools into LiteLLM_ToolTable.r   )Úbatch_upsert_tools)rf   rx  Nz4_flush_tool_discovery_queue error (non-blocking): %s)Ú%litellm.proxy.db.tool_registry_writerr•  r˜   Úflushrr   r   r¿   )rQ   rf   r•  rx  r×   s        rJ   r„  z/DBSpendUpdateWriter._flush_tool_discovery_queue[  sg   è ø€ õ
 	Mð	bØ×4Ñ4×:Ñ:Ó<ˆEÙÙ(°}ÈEÔR×RÑRð ØRùÜò 	bÜ ×&Ñ&Ð']Ð_`×aÑaûð	büs7   ‚A(Š)< ³:´< ¸A(º< ¼	A%ÁA ÁA(Á A%Á%A(r×   Úattemptc              ƒ   ó<  K  — ddl m} ddlm} t	        | t
        «      xs |j                  | «      }|r||k\  r || ||¬«       t        j                  d|dz   || «       t        j                  t        j                  d|z  d|dz   z  «      «      ƒ d{  –—†  y7 Œ­w)	zYRetry a failed spend-update transaction on connection errors or deadlocks, else re-raise.r   ©ÚPrismaDBExceptionHandler©Ú$_raise_failed_update_spend_exception©r×   r¨   rL  zBRetrying spend update after retryable DB error (attempt %s/%s): %sé   é   N)Ú"litellm.proxy.db.exception_handlerr›  r¾   r�  r€   r   Úis_deadlock_errorr   ÚwarningrÇ   ÚsleepÚrandomÚuniform)r×   r˜  rK  r¨   rL  r›  r�  Úis_retryables           rJ   Ú_handle_spend_update_failurez0DBSpendUpdateWriter._handle_spend_update_failurei  s�   è ø€ õ 	PÝLä! !Ô%>Ó?ÒpÐC[×CmÑCmÐnoÓCpˆÙ˜w¨-Ò7Ù0°1ÀÐ_pÕqÜ×$Ñ$ØPØ�a‰KØØô		
ô �m‰mœFŸN™N¨1¨g©:°q¸WÀq¹[Ñ7IÓJÓK×KÒKús   ‚BBÂBÂBrV  c              ƒ   óØ  K  — ddl m} |d   }t        j                  d|«       |�Öt	        |j                  «       «      dkD  rºt        |dz   «      D ]©  }t        j                  «       }	 t        |«      4 ƒd{  –—† }	|	j                  «       4 ƒd{  –—† }
t        |j                  «       «      D ](  \  }}|
j                  j                  d|idd	|ii¬
«       Œ* ddd«      ƒd{  –—†  ddd«      ƒd{  –—†   n |d   }t        j                  d|«       |�9t	        |j                  «       «      dkD  r|j!                  ||||¬«      ƒ d{  –—†  |d   }t        j                  d|«       |�øt	        |j                  «       «      dkD  rÜt        |dz   «      D ]Ë  }t        j                  «       }	 t        |«      4 ƒd{  –—† }	|	j                  «       4 ƒd{  –—† }
t        |j                  «       «      D ]J  \  }}|
j"                  j                  d|id	|it%        j&                  t(        j*                  «      dœ¬
«       ŒL ddd«      ƒd{  –—†  ddd«      ƒd{  –—†   n |d   }t        j                  d|«       |�ít	        |j                  «       «      dkD  rÑt        |dz   «      D ]À  }t        j                  «       }	 t        |«      4 ƒd{  –—† }	|	j                  «       4 ƒd{  –—† }
t        |j                  «       «      D ]?  \  }}t        j                  d||«       |
j,                  j                  d|idd	|ii¬
«       ŒA ddd«      ƒd{  –—†  ddd«      ƒd{  –—†   n |d   }t        j                  d|«       |��«t	        |j                  «       «      dkD  �rŽg }|D ]=  }|j/                  d«      d   }|j/                  d«      d   }|j1                  ||f«       Œ? t        |dz   «      D ]Õ  }t        j                  «       }	 t        |«      4 ƒd{  –—† }	|	j                  «       4 ƒd{  –—† }
t        |j                  «       «      D ]T  \  }}|j/                  d«      d   }|j/                  d«      d   }|
j2                  j                  ||dœd	|id	|idœ¬
«       ŒV ddd«      ƒd{  –—†  ddd«      ƒd{  –—†   n |rb|�`|j4                  j7                  d«      }|�C|D ]>  \  }}d|› d|› �}|j9                  |¬ «      ƒ d{  –—†  t        j                  d!||«       Œ@ |d"   }t        j                  d#|«       |�Öt	        |j                  «       «      dkD  rºt        |dz   «      D ]©  }t        j                  «       }	 t        |«      4 ƒd{  –—† }	|	j                  «       4 ƒd{  –—† }
t        |j                  «       «      D ](  \  }}|
j:                  j                  d$|idd	|ii¬
«       Œ* ddd«      ƒd{  –—†  ddd«      ƒd{  –—†   n |d%   }t<        j?                  d&|d'd(|||¬)«      ƒ d{  –—†  |j7                  d*«      }t<        j?                  d+|d,d-|||¬)«      ƒ d{  –—†  |d.   }t<        j?                  d/|d0d1|||¬)«      ƒ d{  –—†  y7 �Œ>7 �Œ(7 �Œ×# 1 ƒd{  –—†7  sw Y   �ŒèxY w7 �Œà# 1 ƒd{  –—†7  sw Y   �ŒñxY w# t        $ r*}| j                  |||||¬«      ƒ d{  –—†7   Y d}~�ŒËd}~ww xY w7 �ŒÖ7 �Œf7 �ŒP7 �ŒÝ# 1 ƒd{  –—†7  sw Y   �ŒîxY w7 �Œæ# 1 ƒd{  –—†7  sw Y   �Œ÷xY w# t        $ r*}| j                  |||||¬«      ƒ d{  –—†7   Y d}~�Œód}~ww xY w7 �Œ¿7 �Œ©7 �ŒA# 1 ƒd{  –—†7  sw Y   �ŒRxY w7 �ŒJ# 1 ƒd{  –—†7  sw Y   �Œ[xY w# t        $ r*}| j                  |||||¬«      ƒ d{  –—†7   Y d}~�ŒLd}~ww xY w7 �ŒÝ7 �ŒÇ7 �ŒJ# 1 ƒd{  –—†7  sw Y   �Œ[xY w7 �ŒS# 1 ƒd{  –—†7  sw Y   �ŒdxY w# t        $ r*}| j                  |||||¬«      ƒ d{  –—†7   Y d}~�Œjd}~ww xY w7 �ŒT7 �ŒË7 �Œµ7 �Œd# 1 ƒd{  –—†7  sw Y   �ŒuxY w7 �Œm# 1 ƒd{  –—†7  sw Y   �Œ~xY w# t        $ r*}| j                  |||||¬«      ƒ d{  –—†7   Y d}~�ŒXd}~ww xY w7 �Œ�7 �Œ^7 �Œ8­w)2zN
        Commits all the spend `UPDATE` transactions to the Database

        r   )r®   r^  zUser Spend transactions: %sNrŸ  r¢   r´   Ú	increment©ÚwhereÚdata©r×   r˜  rK  r¨   rL  ra  zEnd-User Spend transactions: %s)rK  rf   rL  ra  r]  zKEY Spend transactions: %sr¡   )r´   Úlast_activer_  zTeam Spend transactions: %sz#Updating spend for team id=%s by %sr¤   rb  z&Team Membership Spend transactions: %sz::é   )r¤   r¢   )r´   Útotal_spendÚuser_api_key_cachezteam_membership:ú:©Úkeyz<Invalidated team membership cache for user_id=%s, team_id=%sr`  zOrg Spend transactions: %sr¸   rc  ÚTagrA   r?  )Úentity_namer�  Útable_accessorÚwhere_fieldrK  rf   rL  re  zModel access grouprC   Úaccess_group_namerd  ÚAgentrB   r  ) r¾   r®   r   r¿   ro  ÚkeysÚrangeÚtimerm   r`   Úsortedrx  r<   Úupdate_manyrr   r¨  Úupdate_end_user_spendr=   r   Únowr   Úutcr>   ÚsplitrÕ   r?   Úcall_detailsr„   Úasync_delete_cacher@   r’   Ú_update_entity_spend_in_db)rQ   rf   rK  rL  rV  r®   r^  Úir¨   rÖ   Úbatcherr¢   rª   r×   ra  r]  r¡   r_  r¤   rb  Úteam_memberships_to_invalidaterµ  r²  Ú	cache_keyr`  r¥   rc  re  rd  s                                rJ   rp  z/DBSpendUpdateWriter._commit_spend_updates_to_db€  sÄ	  è ø€ õ 	9ð )EÐE]Ñ(^ÐÜ×"Ñ"Ð#@ÐBXÔYØ!Ð-´#Ð6L×6QÑ6QÓ6SÓ2TÐWXÒ2XÜ˜=¨1Ñ,Ó-ò �Ü!ŸY™Y›[�
ðÜ/°Ó>÷ 	"ð 	"À+Ø#.×#5Ñ#5Ó#7÷ "ð "¸7ô ;AÐAW×A]ÑA]ÓA_Ó:`ò "Ñ 6 ¨Ø '× 9Ñ 9× EÑ EØ+4°gÐ*>Ø*1°KÀÐ3OÐ)Pð !Fõ !"ð"÷	"÷ "÷	"÷ 	"ñ ðð0 -IÐIeÑ,fÐ"Ü×"Ñ"Ð#DÐF`ÔaØ%Ð1´cÐ:T×:YÑ:YÓ:[Ó6\Ð_`Ò6`Ø"×8Ñ8Ø+Ø+Ø"3Ø+Eð	 9ó ÷ ð ð (DÐD[Ñ'\ÐÜ×"Ñ"Ð#?ÐAVÔWØ Ð,´Ð5J×5OÑ5OÓ5QÓ1RÐUVÒ1VÜ˜=¨1Ñ,Ó-ò �Ü!ŸY™Y›[�
ðÜ/°Ó>÷ 
"ð 
"À+Ø#.×#5Ñ#5Ó#7÷ 	"ð 	"¸7ä8>Ð?T×?ZÑ?ZÓ?\Ó8]ò "Ñ 4  }Ø '× AÑ A× MÑ MØ+2°EÐ*:à2=¸}Ð1MÜ7?·|±|ÄHÇLÁLÓ7Qñ*&ð !Nõ !"ð"÷	"÷ 	"÷
"÷ 
"ñ ðð2 )EÐE]Ñ(^ÐÜ×"Ñ"Ð#@ÐBXÔYØ!Ð-´#Ð6L×6QÑ6QÓ6SÓ2TÐWXÒ2XÜ˜=¨1Ñ,Ó-ò �Ü!ŸY™Y›[�
ðÜ/°Ó>÷ 
"ð 
"À+Ø#.×#5Ñ#5Ó#7÷ 	"ð 	"¸7ä:@ÐAW×A]ÑA]ÓA_Ó:`ò "Ñ 6 ¨Ü 4× :Ñ :Ø$IÈ7ÐTaô!"ð !(× 9Ñ 9× EÑ EØ+4°gÐ*>Ø*1°KÀÐ3OÐ)Pð !Fõ !"ð	"÷	"÷ 	"÷
"÷ 
"ñ ðð2 0LÐLkÑ/lÐ%Ü×"Ñ"Ð#KÐMjÔkØ(Ñ4¼Ð=Z×=_Ñ=_Ó=aÓ9bÐefÓ9fàKMÐ*Ø4ò J�àŸ)™) D›/¨!Ñ,�ØŸ)™) D›/¨!Ñ,�Ø.×5Ñ5°wÀÐ6HÕIð	Jô ˜=¨1Ñ,Ó-ò �Ü!ŸY™Y›[�
ðÜ/°Ó>÷ "ð "À+Ø#.×#5Ñ#5Ó#7÷ "ð "¸7ô 7=Ð=Z×=`Ñ=`Ó=bÓ6cò "Ñ 2  ]à*-¯)©)°D«/¸!Ñ*< Ø*-¯)©)°D«/¸!Ñ*< à '× >Ñ >× JÑ JØ6=È'Ñ*Rà2=¸}Ð1MØ8CÀ]Ð7Sñ*&ð !Kõ !"ð"÷"÷ "÷"÷ "ñ" ð)ñ@ .Ð2CÐ2OØ,=×,JÑ,J×,NÑ,NÐOcÓ,dÐ"Ø%Ð1Ø,Jò Ñ(˜ Ø&6°w°i¸qÀÀ	Ð$J˜	Ø0×CÑCÈ	ÐCÓR×RÐRÜ,×2Ñ2ØZÐ\cÐelõðð (DÐD[Ñ'\ÐÜ×"Ñ"Ð#?ÐAVÔWØ Ð,´Ð5J×5OÑ5OÓ5QÓ1RÐUVÒ1VÜ˜=¨1Ñ,Ó-ò �Ü!ŸY™Y›[�
ðÜ/°Ó>÷ "ð "À+Ø#.×#5Ñ#5Ó#7÷ "ð "¸7ä9?Ð@U×@[Ñ@[Ó@]Ó9^ò "Ñ 5 ¨Ø '× AÑ A× MÑ MØ+<¸fÐ*EØ*1°KÀÐ3OÐ)Pð !Nõ !"ð"÷"÷ "÷"÷ "ñ ðð, (DÐD[Ñ'\ÐÜ!×<Ñ<ØØ.Ø-Ø"Ø'Ø'Ø/ð =ó 
÷ 	
ð 	
ð 7S×6VÑ6VØ2ó7
Ð,ô "×<Ñ<Ø,Ø=Ø@Ø+Ø'Ø'Ø/ð =ó 
÷ 	
ð 	
ð *FÐF_Ñ)`ÐÜ!×<Ñ<ØØ0Ø0Ø"Ø'Ø'Ø/ð =ó 
÷ 	
ñ 	
ðC	"ùð"ùð "ù÷ "÷ "ò "úð	"ù÷ 	"÷ 	"ò 	"ûô !ò Ø×;Ñ;ØØ !Ø&3Ø#-Ø*;ð <ó ÷ ÷ ûðúðùð
"ùð	"ùð 	"ù÷ 	"÷ 	"ò 	"úð
"ù÷ 
"÷ 
"ò 
"ûô !ò Ø×;Ñ;ØØ !Ø&3Ø#-Ø*;ð <ó ÷ ÷ ûðúð 
"ùð	"ùð 	"ù÷ 	"÷ 	"ò 	"úð
"ù÷ 
"÷ 
"ò 
"ûô !ò Ø×;Ñ;ØØ !Ø&3Ø#-Ø*;ð <ó ÷ ÷ ûðúð0"ùð"ùð "ù÷ "÷ "ò "úð"ù÷ "÷ "ò "ûô$ !ò Ø×;Ñ;ØØ !Ø&3Ø#-Ø*;ð <ó ÷ ÷ ûðúð  Sùð"ùð"ùð "ù÷ "÷ "ò "úð"ù÷ "÷ "ò "ûô !ò Ø×;Ñ;ØØ !Ø&3Ø#-Ø*;ð <ó ÷ ÷ ûðúð	
ùð	
ùð	
ûs7  ‚A%c*Á([-Á7Z5Á8[-Á;[ÂZ8
Â[ÂAZ>Ã[Ã$Z;Ã%[Ã)[-Ã4[Ã5[-Ã9Ac*Å\#ÅA"c*Æ1]Ç \&Ç]Ç]Ç\)
Ç]ÇA'\/É]É\,É]É]É]É ]É$A!c*Ë_Ë^Ë_Ë^6Ë.^
Ë/^6Ë2A^Í^6Í^Í^6Í_Í)^3Í*_Í.B'c*Ð`:Ð%`Ð&`:Ð)`$Ð>`
Ð?`$ÑA1`Ò3`$Ò>`Ò?`$Ó`:Ó`!Ó`:ÓA	c*Ôa0ÔA;c*Öb+Ö(a3Ö)b+Ö,b×a6
×b×Aa<Ø
bØa9ØbØb+Ø%bØ&b+Ø*'c*Ùc!Ù4c*Úc$Ú(c*Ú/c'Ú0c*Ú5[-Ú8[Ú;[Ú>[Û[Û[Û[Û[-Û[*	Û[ Û[*	Û%[-Û-	\ Û6\Ü\Ü\Üc*Ü\ Ü c*Ü&]Ü)]Ü,]Ü/]Ü5\8Ü6]Ü=]Ý]Ý]	Ý]Ý]	Ý]Ý	^Ý'^Þ ^Þ^Þc*Þ^Þc*Þ_Þ^6Þ^6Þ^0Þ#^&Þ$^0Þ+^6Þ3_Þ6_		Þ<^?Þ=_		ß_ß	_?ß_:ß._1ß/_:ß4c*ß:_?ß?c*à`:à`$à`$à`à`à`à`$à!`:à$`7	à*`-à+`7	à2`:à:	a-áa(áaáa(á"c*á(a-á-c*á3b+á6bá9bá<bâbâbâ
bâb+âb(	âbâb(	â#b+â+	câ4cãcãcãc*ãcãc*ã$c*ã'c*r·  r�  r¸  )rA   rB   rC   r¹  c              ƒ   óú  K  — t        j                  d| |«       |�ñt        |j                  «       «      dkD  rÔt	        |dz   «      D ]Â  }t        j
                  «       }	 t        |«      4 ƒd{  –—† }	|	j                  «       4 ƒd{  –—† }
t        |j                  «       «      D ]A  \  }}t        j                  d| |||«       t        |
|«      j                  ||idd|ii¬«       ŒC ddd«      ƒd{  –—†  ddd«      ƒd{  –—†   y yyy7 Œ 7 Œ‰7 Œ# 1 ƒd{  –—†7  sw Y   Œ.xY w7 Œ%# 1 ƒd{  –—†7  sw Y    yxY w# t        $ r.}t        j                  |||||¬	«      ƒ d{  –—†7   Y d}~�Œ-d}~ww xY w­w)
a`  
        Helper function to update spend for any entity type (team, org, tag, etc).

        Args:
            entity_name: Name of entity for logging (e.g., "Team", "Org", "Tag")
            transactions: Dictionary of {entity_id: response_cost}
            table_accessor: Prisma table accessor (e.g., prisma_client.db.litellm_teamtable)
            where_field: Field name for where clause (e.g., "team_id", "organization_id", "tag_name")
            n_retry_times: Number of retries on failure
            prisma_client: Prisma client instance
            proxy_logging_obj: Proxy logging object
        z%s Spend transactions: %sNr   rŸ  z!Updating spend for %s %s=%s by %sr´   rª  r«  r®  )r   r¿   ro  r¼  r½  r¾  rm   r`   r¿  rx  ÚgetattrrÀ  rr   r’   r¨  )r·  r�  r¸  r¹  rK  rf   rL  rÈ  r¨   rÖ   rÉ  r&  rª   r×   s                 rJ   rÇ  z.DBSpendUpdateWriter._update_entity_spend_in_db_  s–  è ø€ ô, 	×"Ñ"Ð#>ÀÈ\ÔZØÐ#¬¨L×,=Ñ,=Ó,?Ó(@À1Ò(DÜ˜=¨1Ñ,Ó-ò �Ü!ŸY™Y›[�
ðÜ/°Ó>÷ "ð "À+Ø#.×#5Ñ#5Ó#7÷ "ð "¸7ä<BÀ<×CUÑCUÓCWÓ<Xò "Ñ 8 	¨=Ü 4× :Ñ :Ø$GØ$/Ø$/Ø$-Ø$1ô!"ô !(¨°Ó @× LÑ LØ+6¸	Ð*BØ*1°KÀÐ3OÐ)Pð !Mõ !"ð"÷"÷ "÷"÷ "ñ ñ%ð )EÐ#ð"øð"øð "ø÷ "÷ "ñ "úð"ø÷ "÷ "ð "ñ ûÜ ò Ü-×JÑJØØ !Ø&3Ø#-Ø*;ð Kó ÷ ÷ ûðüsÙ   ‚AE;ÁEÁ-DÁ.EÁ1D+ÂD
ÂD+Â
ADÃ(D+Ã3DÃ4D+Ã8EÄD)ÄEÄE;ÄEÄD+ÄD+ÄD&ÄDÄD&Ä"D+Ä)EÄ+D>	Ä1D4Ä2D>	Ä9EÄ<E;Ä>EÅ	E8Å
E3Å'E*Å(E3Å-E;Å3E8Å8E;rh  r%  ÚuserÚentity_id_fieldc              ƒ   ó   K  — y ­wrO   rH   ©rK  rf   rL  rh  r%  rÏ  s         rJ   Ú_update_daily_spendz'DBSpendUpdateWriter._update_daily_spend•  ó   è ø€ ð 	ùrT   Úteamc              ƒ   ó   K  — y ­wrO   rH   rÑ  s         rJ   rÒ  z'DBSpendUpdateWriter._update_daily_spend¡  rÓ  rT   Úorgc              ƒ   ó   K  — y ­wrO   rH   rÑ  s         rJ   rÒ  z'DBSpendUpdateWriter._update_daily_spend­  rÓ  rT   Úend_userc              ƒ   ó   K  — y ­wrO   rH   rÑ  s         rJ   rÒ  z'DBSpendUpdateWriter._update_daily_spend¹  rÓ  rT   Úagentc              ƒ   ó   K  — y ­wrO   rH   rÑ  s         rJ   rÒ  z'DBSpendUpdateWriter._update_daily_spendÅ  rÓ  rT   Útagc              ƒ   ó   K  — y ­wrO   rH   rÑ  s         rJ   rÒ  z'DBSpendUpdateWriter._update_daily_spendÑ  rÓ  rT   )rÎ  rÔ  rÖ  rÜ  rØ  rÚ  c              ƒ   óÔ  ‡K  — ddl m} t        j                  d|j	                  «       t        |«      «       d}t        j                  «       }	 |�r%t        | dz   «      D �]  }		 t        t        |j                  «       ˆfd„¬«      d| «      }
t        |
«      dk(  rt        j                  d	|«        yt        |   }	 t        |t        |
j                  «       «      ¬
«      }t        ||¬«      \  }} |j                   j"                  |g|¢­Ž ƒ d{  –—†  t        j                  dt        |
«      › d|› dt        j                  «       |z
  d›d�«       |
D ]  }|j-                  |d«       Œ  n |r�Œ$yy7 Œd# t$        $ r3}t'        d||j(                  t        |
«      t+        |«      |¬«       ‚ d}~ww xY w# t$        $ r‚}ddlm} t3        |t4        «      xs |j7                  |«      }|s‚ |	| k\  r ||||¬«       t9        j:                  t=        j>                  d|	z  d|	dz   z  «      «      ƒ d{  –—†7   Y d}~�Œßd}~ww xY w# t$        $ r} ||||¬«       Y d}~yd}~ww xY w­w)zt
        Generic function to update daily spend for any entity type (user, team, org, tag, end_user, agent)
        r   rœ  zDaily %s Spend transactions: %séd   rŸ  c                 óî   •— | d   j                  d«      xs d| d   j                  ‰«      xs d| d   j                  d«      xs d| d   j                  d«      xs d| d   j                  d«      xs dfS )NrŸ  Údater·   Úapi_keyrÝ   rÞ   )r„   )ÚxrÏ  s    €rJ   ú<lambda>z9DBSpendUpdateWriter._update_daily_spend.<locals>.<lambda>  st   ø€ Ø$% a¡D§H¡H¨VÓ$4Ò$:¸Ø$% a¡D§H¡H¨_Ó$=Ò$CÀØ$% a¡D§H¡H¨YÓ$7Ò$=¸2Ø$% a¡D§H¡H¨WÓ$5Ò$;¸Ø$% a¡D§H¡HÐ-BÓ$CÒ$IÀrð/"€ rI   r´  Nz8No new transactions to process for daily %s spend update)Útabler�  )rå  ÚbatchzBDaily %s spend batch upsert failed. Table: %s, Rows: %d, Error: %sr)  z
Processed z daily z transactions in z.2fÚsrš  rž  r   ) r¾   r�  r   r¿   Ú
capitalizero  r¾  r½  rè   r¿  rx  r$   r&   r†   Úvaluesr%   rk   Úexecute_rawrr   r4   rÿ   ry   rq  r¡  r›  r€   r   r¢  rÇ   r¤  r¥  r¦  )rK  rf   rL  rh  r%  rÏ  r�  Ú
BATCH_SIZEr¨   rÈ  Útransactions_to_processrå  Úmerged_batchÚsqlÚparamsÚbatch_errorrµ  r×   r›  r§  s        `              rJ   rÒ  z'DBSpendUpdateWriter._update_daily_spendÞ  s³  øè ø€ õ" 	Mä×"Ñ"Ø-¨{×/EÑ/EÓ/GÌÐMeÓIfô	
ð  ˆ
Ü ŸI™I›Kˆ
ð\	rÚ*Ü˜}¨qÑ0Ó1ó W�AðVô 37Ü"Ø 8× >Ñ >Ó @ó%"ôð" *˜zð#+ó3Ð/ô* Ð6Ó7¸1Ò<Ü0×6Ñ6Ø ZÐ\gôñ #ä 2°;Ñ ?˜ð"ô ,AØ&+¼%Ð@W×@^Ñ@^Ó@`Ó:aô,˜Lô +<À%È|Ô*\™K˜C Ø"> -×"2Ñ"2×">Ñ">¸sÐ"LÀVÒ"L×LÐLô -×2Ñ2Ø(¬Ð-DÓ)EÐ(FÀgÈkÈ]ÐZkÔlp×luÑluÓlwð  {Eñ  mEð  FIð  lJð  JKð  Lôð
 $;ò D˜CØ4×8Ñ8¸¸dÕCðDñ ð}Wõ +ðR MùÜ(ò "ô ,Ø dØ +Ø %§
¡
Ü #Ð$;Ó <Ü # KÓ 0Ø$/õð "ûð"ûô. %ò õô (2ØÔ8ó(ò (Kà5×GÑGÈÓJð %ñ  ,Ø!Ø Ò-Ù@Ø"#Ø+5Ø2Cõô
 &Ÿm™mô #ŸN™N¨1¨a©4°°q¸1±u±Ó>ó÷ ÷ ûð!ûô2 ò 	rÙ0°1ÀÐ_p×qÒqûð	rüs²   ƒAI(ÁI Á%AF9Â3I Â4I(Â5	F9Â?AE:ÄE8ÄE:ÄAF9Å/I Å6I(Å8E:Å:	F6Æ.F1Æ1F6Æ6F9Æ9	IÇA1H?È3H6È4H?È9I È?IÉI É	I%ÉI ÉI(É I%É%I(c              ƒ   óV   K  — t         j                  | |||dd¬«      ƒ d{  –—†  y7 Œ­w)zk
        Batch job to update LiteLLM_DailyUserSpend table using in-memory daily_spend_transactions
        rÎ  r¢   rÑ  N©r’   rÒ  rg  s       rJ   rr  z+DBSpendUpdateWriter.update_daily_user_spendU  ó7   è ø€ ô "×5Ñ5Ø'Ø'Ø/Ø%=ØØ%ð 6ó 
÷ 	
ò 	
úó   ‚)¡'¢)c              ƒ   óV   K  — t         j                  | |||dd¬«      ƒ d{  –—†  y7 Œ­w)zk
        Batch job to update LiteLLM_DailyTeamSpend table using in-memory daily_spend_transactions
        rÔ  r¤   rÑ  Nrò  rg  s       rJ   rs  z+DBSpendUpdateWriter.update_daily_team_spendh  ró  rô  c              ƒ   óV   K  — t         j                  | |||dd¬«      ƒ d{  –—†  y7 Œ­w)zs
        Batch job to update LiteLLM_DailyOrganizationSpend table using in-memory daily_spend_transactions
        rÖ  r¸   rÑ  Nrò  rg  s       rJ   rt  z*DBSpendUpdateWriter.update_daily_org_spend{  s7   è ø€ ô "×5Ñ5Ø'Ø'Ø/Ø%=ØØ-ð 6ó 
÷ 	
ò 	
úrô  c              ƒ   óV   K  — t         j                  | |||dd¬«      ƒ d{  –—†  y7 Œ­w)zn
        Batch job to update LiteLLM_DailyEndUserSpend table using in-memory daily_spend_transactions
        rØ  r£   rÑ  Nrò  rg  s       rJ   ru  z/DBSpendUpdateWriter.update_daily_end_user_spendŽ  s7   è ø€ ô "×5Ñ5Ø'Ø'Ø/Ø%=Ø"Ø)ð 6ó 
÷ 	
ò 	
úrô  c              ƒ   óV   K  — t         j                  | |||dd¬«      ƒ d{  –—†  y7 Œ­w)zl
        Batch job to update LiteLLM_DailyAgentSpend table using in-memory daily_spend_transactions
        rÚ  r  rÑ  Nrò  rg  s       rJ   rv  z,DBSpendUpdateWriter.update_daily_agent_spend¡  s7   è ø€ ô "×5Ñ5Ø'Ø'Ø/Ø%=ØØ&ð 6ó 
÷ 	
ò 	
úrô  c              ƒ   óV   K  — t         j                  | |||dd¬«      ƒ d{  –—†  y7 Œ­w)zj
        Batch job to update LiteLLM_DailyTagSpend table using in-memory daily_spend_transactions
        rÜ  rÑ  Nrò  rg  s       rJ   r†  z*DBSpendUpdateWriter.update_daily_tag_spend´  s7   è ø€ ô "×5Ñ5Ø'Ø'Ø/Ø%=ØØ!ð 6ó 
÷ 	
ò 	
úrô  Útype)rÎ  rÔ  rÖ  r  rØ  rÚ  c              ƒ   ó   ‡K  — ddg}|dk(  rdg|¢}nE|dk(  rdg|¢}n:|dk(  rdg|¢}n/|dk(  rdg|¢}n$|d	k(  rd
g|¢}n|dk(  rdg|¢}nt        d|› �«      ‚t        ˆfd„|D «       «      st        j                  d|«       y ddg}t	        ˆfd„|D «       «      st        j                  d|«       y d‰v rn"d‰v rd‰vsd‰vrt        j                  d«       y |j                  ‰«      }t        j                  d|«       t        j                  ‰d   «      }|j                  di «      xs i }	t        ‰d   t        «      r(‰d   j                  «       }
|
j                  d«      d   }nEt        ‰d   t        «      r‰d   j                  d«      d   }nt        j                  d‰d   «       y 	 ‰j                  dd «      }d }|rt        j                  |d «      }t        |j                  t         «      «      }t#        |	«      }t%        |«      }t'        ‰j                  dd «      ‰j                  dd «      |t)        |‰j                  d«      «      |j                  d«      ‰j                  d«      t*        |	|j                  d «      |j                  d!«      ¬"«
      }t-        d5i d#|“d‰d   “d‰j                  dd «      “d‰j                  dd «      “d‰j                  dd «      “d‰j                  dd «      “d$|“d%‰d%   “d&‰d&   “d'‰d'   “d(|rdnd)“d*|s|d+k(  rd)nd“d,|s|d+k7  rd)nd“d-|“d.t/        |	«      “d/|“d0|j0                  “d1|j2                  “d2|j4                  “d3|rd4n|j6                  “Ž}|S # t8        $ r}|‚d }~ww xY w­w)6Nrµ   râ  rÎ  rÔ  r¤   rÖ  r¸   r  rØ  r£   rÚ  r  zInvalid type: c              3   ó&   •K  — | ]  }|‰v –— Œ
 y ­wrO   rH   ©r�   rµ  rº   s     €rJ   rƒ   z]DBSpendUpdateWriter._common_add_spend_log_transaction_to_daily_transaction.<locals>.<genexpr>Ü  s   øè ø€ Ò; c�3˜'”>Ñ;ùó   ƒzRMissing expected keys: %s, in payload, skipping from daily_user_spend_transactionsrÝ   rÎ   c              3   ó&   •K  — | ]  }|‰v –— Œ
 y ­wrO   rH   rý  s     €rJ   rƒ   z]DBSpendUpdateWriter._common_add_spend_log_transaction_to_daily_transaction.<locals>.<genexpr>ã  s   øè ø€ Ò? c�3˜'”>Ñ?ùrþ  zVMissing any expected keys: %s, in payload, skipping from daily_user_spend_transactionsrÞ   Úmodel_groupzbMissing custom_llm_provider or model_group in payload, skipping from daily_user_spend_transactionszLogged request status: %srÙ   rÜ   ÚTr   zCInvalid start time: %s, skipping from daily_user_spend_transactionsrH  rß   rÚ   rà   rá   )
rÝ   rÞ   râ   rã   rÚ   rß   rp   rÜ   rà   rä   rá  ÚendpointÚprompt_tokensÚcompletion_tokensr´   Úapi_requestsrŸ  Úsuccessful_requestsÚsuccessÚfailed_requestsÚcache_read_input_tokensÚcache_creation_input_tokensrâ   Úcompression_savings_spendÚprompt_caching_savings_spendÚ&gateway_injected_caching_savings_spendÚautorouter_savings_spendr³   rH   )Ú
ValueErrorÚallr   r¿   ÚanyÚget_request_statusræ   rç   r„   r€   r   rÃ   rÄ  ry   r.   r\   r   r2   r/   r0   r3   rs   r   r1   ÚcompressionÚprompt_cachingÚgateway_injected_cachingrê   rr   )rQ   rº   rf   rú  Úcommon_expected_keysÚexpected_keysÚany_expected_keysÚrequest_statusr  Ú	usage_objr¨   rá  rH  r  Úis_internal_callr	  râ   rï   Údaily_transactionr×   s    `                  rJ   Ú6_common_add_spend_log_transaction_to_daily_transactionzJDBSpendUpdateWriter._common_add_spend_log_transaction_to_daily_transactionÇ  sO  øè ø€ ð (3°IÐ&>ÐØ�6Š>Ø#Ð;Ð&:Ð;‰MØ�VŠ^Ø&Ð>Ð)=Ð>‰MØ�UŠ]Ø.ÐFÐ1EÐF‰MØ�^Ò#Ø+ÐCÐ.BÐC‰MØ�ZÒØ*ÐBÐ-AÐB‰MØ�WŠ_Ø'Ð?Ð*>Ð?‰Mä˜~¨d¨VÐ4Ó5Ð5ÜÓ;¨]Ô;Ô;Ü ×&Ñ&ØdÐfsôð à$+Ð-GÐ#HÐÜÓ?Ð->Ô?Ô?Ü ×&Ñ&ØhØ!ôð Ø'¨7Ñ2ØØ˜ÑÐ%:À'Ñ%IÈ]ÐbiÑMiÜ ×&Ñ&Øtôð ð !.× @Ñ @ÀÓ IˆÜ×"Ñ"Ð#>ÀÔOÜ.2¯j©j¸ÀÑ9LÓ.Mˆ	Ø$Ÿ=™=¨¸Ó<ÒBÀˆ	Ü�g˜kÑ*¬HÔ5Ø '¨Ñ 4× >Ñ >Ó @ˆJØ×#Ñ# CÓ(¨Ñ+‰DÜ˜ Ñ,¬cÔ2Ø˜;Ñ'×-Ñ-¨cÓ2°1Ñ5‰Dä ×&Ñ&ØUÐW^Ð_jÑWkôð ð4	à&Ÿ{™{¨;¸Ó=ˆIØˆHÙÜ1×5Ñ5°iÀÓF�ä&*¨9¯=©=Ô9ZÓ+[Ó&\ÐÜ-FÀyÓ-QÐ#Ü.NÈyÓ.YÐ$Ü#8Ø—k‘k '¨4Ó0Ø$+§K¡KÐ0EÀtÓ$LØ)AÜ'>¸yÈ'Ï+É+ÐV`ÓJaÓ'bØ!*§¡Ð/AÓ!BØ Ÿ™ ZÓ0Ü)Ø&Ø(Ÿ}™}Ð-=Ó>Ø,5¯M©MÐ:NÓ,Oô$ˆMô (Aò (Ùð(à 	Ò*ð(ð —k‘k '¨4Ô0ð(ð $ŸK™K¨°tÔ<ð	(ð
 *1¯©Ð5OÐQUÔ)Vð(ð %,§K¡KÐ0EÀtÔ$Lð(ñ "ð(ð & oÒ6ð(ð #*Ð*=Ò">ð(ð ˜gÒ&ð(ñ  #3™Q¸øð!(ñ" .>À.ÐT]ÒB]¡AÐcdøð#(ñ$ *:¸nÐPYÒ>Y¡Ð_`øð%(ñ& )@ð'(ô( -JÈ)Ô,Tð)(ñ* *Bð+(ð, +8×*CÒ*Cð-(ð. .;×-IÒ-Ið/(ð0 8E×7]Ò7]ð1(ñ2 1A©Àm×F^ÑF^øð3(Ðð6 %Ð$øÜò 	ØˆGûð	üs+   ƒF+NÆ/GM; Í:NÍ;	NÎNÎNÎNc              ƒ   óZ  K  — |€t        j                  d«       y| j                  ||d«      ƒ d{  –—† }|€y|j                  d«      xs d}|d   › d|d   › d|d   › d|d	   › d|d
   › d|› �}t	        dd|d   i|¤Ž}| j
                  j                  ||i¬«      ƒ d{  –—†  y7 Œu7 Œ­w)zî
        Add a spend log transaction to the `daily_spend_update_queue`

        Key = @@unique([user_id, date, api_key, model, custom_llm_provider])    )

        If key exists, update the transaction with the new spend and usage
        NrI  rÎ  r  r·   Ú_rá  râ  rÝ   rÞ   r¢   r'  rH   )r   r¿   r  r„   r   r™   rú   ©rQ   rº   rf   Úbase_daily_transactionÚendpoint_strÚdaily_transaction_keyr  s          rJ   r  zGDBSpendUpdateWriter.add_spend_log_transaction_to_daily_user_transaction;  s  è ø€ ð Ð Ü ×&Ñ&Ð'bÔcØà.2×.iÑ.iØ�] Fó/
÷ )
Ðð "Ð)Øà4×8Ñ8¸ÓDÒJÈˆØ#*¨6¡?Ð"3°1Ð5KÈFÑ5SÐ4TÐTUÐV]Ð^gÑVhÐUiÐijÐkrÐszÑk{Ðj|Ð|}ð  Fð  G\ñ  ]ð  ~^ð  ^_ð  `lð  _mð  !nÐÜ#<Ñ#oÀWÈVÁ_Ð#oÐXnÑ#oÐØ×+Ñ+×6Ñ6Ð?TÐVgÐ>hÐ6Ói×iÑið)
øð 	jús"   ‚/B+±B'²A/B+Â!B)Â"B+Â)B+c              ƒ   ó�  K  — |€t        j                  d«       y | j                  ||d«      ƒ d {  –—† }|€y |d   €t        j                  d«       y |j                  d«      xs d}|d   › d|d   › d|d	   › d|d
   › d|d   › d|› �}t	        dd|d   i|¤Ž}| j
                  j                  ||i¬«      ƒ d {  –—†  y 7 Œ�7 Œ­w)NrI  rÔ  r¤   z>team_id is None for request. Skipping incrementing team spend.r  r·   r  rá  râ  rÝ   rÞ   r'  rH   )r   r¿   r  r„   r   rš   rú   r   s          rJ   r  zGDBSpendUpdateWriter.add_spend_log_transaction_to_daily_team_transactionV  s:  è ø€ ð
 Ð Ü ×&Ñ&Ð'bÔcØà.2×.iÑ.iØ�] Fó/
÷ )
Ðð "Ð)ØØ�9ÑÐ%Ü ×&Ñ&Ð'gÔhØà4×8Ñ8¸ÓDÒJÈˆØ#*¨9Ñ#5Ð"6°aÐ8NÈvÑ8VÐ7WÐWXÐY`ÐajÑYkÐXlÐlmÐnuÐv}Ñn~Ðmð  @Að  BIð  J_ñ  B`ð  Aað  abð  coð  bpð  !qÐÜ#<Ñ#rÀWÈYÑEWÐ#rÐ[qÑ#rÐØ×0Ñ0×;Ñ;ÐDYÐ[lÐCmÐ;Ón×nÑnð)
øð 	oús"   ‚/C±C²B
CÂ<CÂ=CÃCc              ƒ   óª  K  — |€t        j                  d«       y |€t        j                  d«       y t        t        i |¥d|i¥«      }| j	                  ||d«      ƒ d {  –—† }|€y |j                  d«      xs d}|› d|d   › d|d	   › d|d
   › d|d   › d|› �}t        dd|i|¤Ž}| j                  j                  ||i¬«      ƒ d {  –—†  y 7 Œo7 Œ­w)NrI  zNorganization_id is None for request. Skipping incrementing organization spend.r¸   rÖ  r  r·   r  rá  râ  rÝ   rÞ   r'  rH   )	r   r¿   r   r!   r  r„   r   r�   rú   )	rQ   rº   rf   r¥   Úpayload_with_orgr!  r"  r#  r  s	            rJ   r  zFDBSpendUpdateWriter.add_spend_log_transaction_to_daily_org_transactionm  s\  è ø€ ð Ð Ü ×&Ñ&Ð'bÔcØàˆ>Ü ×&Ñ&Ð'wÔxØä"&ÜðØðà! 6ñó#
Ðð /3×.iÑ.iØ˜m¨Uó/
÷ )
Ðð "Ð)Øà4×8Ñ8¸ÓDÒJÈˆØ#) (¨!Ð,BÀ6Ñ,JÐ+KÈ1ÐM]Ð^gÑMhÐLiÐijÐk{ð  }Dñ  lEð  kFð  FGð  HXð  Ynñ  Hoð  Gpð  pqð  r~ð  qð  !@ÐÜ#DÑ#vÐU[Ð#vÐ_uÑ#vÐØ×/Ñ/×:Ñ:ÐCXÐZkÐBlÐ:Óm×mÑmð)
øð 	nús%   ‚ACÁCÁ A)CÃ	CÃ
CÃCc              ƒ   óÖ  K  — |€t        j                  d«       y |j                  d«      }|�|dk(  rt        j                  d«       y t        t        i |¥d|i¥«      }| j                  ||d«      ƒ d {  –—† }|€y |j                  d«      xs d}|› d|d   › d|d	   › d|d
   › d|d   › d|› �}t        dd|i|¤Ž}| j                  j                  ||i¬«      ƒ d {  –—†  y 7 Œo7 Œ­w)NrI  rØ  r·   zLend_user is None or empty for request. Skipping incrementing end user spend.r£   r  r  rá  râ  rÝ   rÞ   r'  rH   )	r   r¿   r„   r   r!   r  r   r›   rú   )	rQ   rº   rf   r£   Úpayload_with_end_user_idr!  r"  r#  r  s	            rJ   r  zKDBSpendUpdateWriter.add_spend_log_transaction_to_daily_end_user_transactionŽ  sv  è ø€ ð
 Ð Ü ×&Ñ&Ð'bÔcØà$Ÿ[™[¨Ó4ˆØÐ +°Ò"3Ü ×&Ñ&Ð'uÔvØä*.ÜðØðà˜{ñó+
Ð ð /3×.iÑ.iØ$ m°Zó/
÷ )
Ðð "Ð)Øà4×8Ñ8¸ÓDÒJÈˆØ#. -¨qÐ1GÈÑ1OÐ0PÐPQÐRjÐktÑRuÐQvÐvwð  yQð  RYñ  yZð  x[ð  [\ð  ]uð  vKñ  ]Lð  \Mð  MNð  O[ð  N\ð  !]ÐÜ#?Ñ#rÈKÐ#rÐ[qÑ#rÐØ×4Ñ4×?Ñ?ÐH]Ð_pÐGqÐ?Ór×rÑrð)
øð 	sús%   ‚A3C)Á5C%Á6A)C)ÃC'Ã C)Ã'C)c              ƒ   ó˜  K  — |€t        j                  d«       y |d   €y t        t        i |¥d|d   i¥«      }| j	                  ||d«      ƒ d {  –—† }|€y |j                  d«      xs d}|d   › d|d   › d|d   › d|d	   › d|d
   › d|› �}t        dd|d   i|¤Ž}| j                  j                  ||i¬«      ƒ d {  –—†  y 7 Œu7 Œ­w)NrI  r  rÚ  r  r·   r  rá  râ  rÝ   rÞ   r'  rH   )	r   r¿   r   r!   r  r„   r   rœ   rú   )rQ   rº   rf   Úpayload_with_agent_idr!  r"  r#  r  s           rJ   r  zHDBSpendUpdateWriter.add_spend_log_transaction_to_daily_agent_transaction¯  sh  è ø€ ð
 Ð Ü ×&Ñ&Ð'bÔcØØ�:ÑÐ&ØÜ'+ÜðØðà˜G JÑ/ñó(
Ðð /3×.iÑ.iØ! =°'ó/
÷ )
Ðð "Ð)ØØ4×8Ñ8¸ÓDÒJÈˆØ#*¨:Ñ#6Ð"7°qÐ9OÐPVÑ9WÐ8XÐXYÐZoÐpyÑZzÐY{Ð{|ð  ~Sð  T[ñ  ~\ð  }]ð  ]^ð  _tð  uJñ  _Kð  ^Lð  LMð  NZð  M[ð  !\ÐÜ#=Ñ#uÀwÈzÑGZÐ#uÐ^tÑ#uÐØ×1Ñ1×<Ñ<ÐEZÐ\mÐDnÐ<Óo×oÑoð)
øð 	pús%   ‚AC
ÁCÁA/C
Ã CÃC
ÃC
c              ƒ   óP  K  — |€t        j                  d«       y | j                  ||d«      ƒ d {  –—† }|€y |d   €t        j                  d«       y g }t        |d   t        «      rt        j                  |d   «      }n*t        |d   t        «      r|d   }nt        d|d   › �«      ‚|D ]p  }|j                  d«      xs d}|› d|d   › d|d	   › d|d
   › d|d   › d|› �}t        dd|i|¤d|d   i¤Ž}| j                  j                  ||i¬«      ƒ d {  –—†  Œr y 7 Œð7 Œ	­w)NrI  r  zBrequest_tags is None for request. Skipping incrementing tag spend.zInvalid request_tags: r  r·   r  rá  râ  rÝ   rÞ   rÜ  r½   r'  rH   )r   r¿   r  r€   ry   ræ   rç   r…   r  r„   r   rž   rú   )	rQ   rº   rf   r!  r  rÜ  r"  r#  r  s	            rJ   r   zFDBSpendUpdateWriter.add_spend_log_transaction_to_daily_tag_transactionÊ  s¥  è ø€ ð
 Ð Ü ×&Ñ&Ð'bÔcØà.2×.iÑ.iØ�] Nó/
÷ )
Ðð "Ð)ØØ�>Ñ"Ð*Ü ×&Ñ&Ð'kÔlØàˆÜ�g˜nÑ-¬sÔ3ÜŸ:™: g¨nÑ&=Ó>‰LÜ˜ Ñ/´Ô6Ø" >Ñ2‰LäÐ5°g¸nÑ6MÐ5NÐOÓPÐPØò 	rˆCØ1×5Ñ5°jÓAÒGÀRˆLØ'* e¨1Ð-CÀFÑ-KÐ,LÈAÈgÐV_ÑN`ÐMaÐabÐcjÐkrÑcsÐbtÐtuÐv}ð  Tñ  wUð  vVð  VWð  Xdð  Weð  %fÐ!Ü 8ñ !Øð!Ø1ñ!Ø>EÀlÑ>Sò!Ðð ×3Ñ3×>Ñ>ÐG\Ð^oÐFpÐ>Óq×qÑqñ	rð!)
øð. rús"   ‚/D&±D"²C(D&ÄD$ÄD&Ä$D&rO   )NN)rÎ  )HrD   rE   rF   Ú__doc__r   r    ry   rè   r-  ÚModelResponser	   rr   r   ÚfloatrË   r!   rÅ   rÆ   rÊ   r7   r   rÉ   r  r  r  r  r  r  ru   r  ÚosÚgetenvrÄ   Úintr8   rR  rP  rQ  r‰  r�  Ústaticmethodr,   rw  rŒ  r„  r¨  r   rp  r   rÇ  r   r   rÒ  r   r   r   r   r   rr  rs  rt  ru  rv  r†  r   r  r  r  r  r  r  r   rH   rI   rJ   r’   r’   ³   sÈ  „ ñð *.ñBà $Ñ&óBð"zð �T‰zðzð �t‘ð	zð
 ˜4‘Zðzð �t‘ðzð �d‘
ðzð �t‘ðzð %×2Ñ2°SÑ8¸9ÑDÀtÑKðzð ˜t‘Oðzð ˜T‘/ðzð ˜t‘|ðzð 
ˆt‰ózðB !%ñfà!ðfð Nðfð -ð	fð
 ðfð 
ófð<)kà!ð)kð -ð)kð 
ó	)kð^ $(Ø"ñQdà�t‘ðQdð ! 4™ZðQdð ˜D‘jð	Qdð
 �t‘ðQdð 
óQdð~ 68òmð ˜t‘|ðmð �t‘ð	mð
 ˜D‘jðmð �t‘ðmð �d‘
ðmð ˜4‘Zðmð $ dÑ*ðmð $'¨¡:ðmð "ðmð &.¨c¡]ómð^à˜t‘|ðð ˜D‘jðð $ dÑ*ó	ð6 #'ñ-à˜t‘|ð-ð �t‘ð-ð $ dÑ*ð	-ð
 $'¨¡:ð-ð ˜4‘Zó-ð^4à˜t‘|ð4ð �t‘ð4ð �t‘ð	4ð
 $ dÑ*ó4ðlà˜t‘|ðð �d‘
ðð $ dÑ*ó	ð<à˜t‘|ðð ˜‘*ðð $ dÑ*ó	ð60à˜t‘|ð0ð ˜D‘jð0ð $ dÑ*ó	0ðp ,0ñ*à˜t‘|ð*ð &.¨c¡]°TÑ%9ð*ð ˜t™ð	*ð
 $ dÑ*ð*ð " DÑ(ð*ð 
ó*ð^ .2Ø%. R§Y¡YÐ/?Ó%@ñ	àÐ(Ñ(ðð $ dÑ*ðð ˜d™
ð	ð
 
˜Ñ	óð,#à#ð#ð ð#ð (ó	#ðJNà#ðNð ðNð (ó	Nð`xLà#ðxLð ðxLð (ó	xLðtà#ðð ðð (ó	ð.$à#ð$ð ð$ð (ó	$ðL ð
Ø#ð
à#+Ð,BÑ#Cð
ð 
ò
ó ð
ð*à#ðð ðð (ð	ð
 
óð>bà#ðbð 
óbð ðLØðLàðLð ðLð ð	Lð
 (ðLð 
òLó ðLð,]
à#ð]
ð ð]
ð (ð	]
ð
 '@ó]
ð~ ð1Øð1à˜3 ˜:Ñ&¨Ñ-ð1ð  Ð pÑqð1ð ð	1ð
 ð1ð $ð1ð (ò1ó ð1ðj ØðØðà#ðð (ðð #' sÐ,EÐ'EÑ"Fð	ð
 ˜V‘_ðð ðð 
òó ó ðð ØðØðà#ðð (ðð #' sÐ,EÐ'EÑ"Fð	ð
 ˜V‘_ðð ðð 
òó ó ðð ØðØðà#ðð (ðð #' sÐ,MÐ'MÑ"Nð	ð
 ˜U‘^ðð ðð 
òó ó ðð ØðØðà#ðð (ðð #' sÐ,HÐ'HÑ"Ið	ð
 ˜ZÑ(ðð ðð 
òó ó ðð ØðØðà#ðð (ðð #' sÐ,FÐ'FÑ"Gð	ð
 ˜WÑ%ðð ðð 
òó ó ðð ØðØðà#ðð (ðð #' sÐ,DÐ'DÑ"Eð	ð
 ˜U‘^ðð ðð 
òó ó ðð ðtrØðtrà#ðtrð (ðtrð #' sÐ,EÐ'EÑ"FØ
ˆsÐ-Ð-Ñ
.ñ#/à
ˆsÐ,Ð,Ñ
-ñ#.ð ˆsÐ5Ð5Ñ
6ñ#7ð ˆsÐ0Ð0Ñ
1ñ	#2ð
 ˆsÐ.Ð.Ñ
/ñ#0ð	trð ÐNÑOðtrð ðtrð 
òtró ðtrðl ð
Øð
à#ð
ð (ð
ð #' sÐ,EÐ'EÑ"Fò	
ó ð
ð$ ð
Øð
à#ð
ð (ð
ð #' sÐ,EÐ'EÑ"Fò	
ó ð
ð$ ð
Øð
à#ð
ð (ð
ð #' sÐ,MÐ'MÑ"Nò	
ó ð
ð$ ð
Øð
à#ð
ð (ð
ð #' sÐ,HÐ'HÑ"Iò	
ó ð
ð$ ð
Øð
à#ð
ð (ð
ð #' sÐ,FÐ'FÑ"Gò	
ó ð
ð$ ð
Øð
à#ð
ð (ð
ð #' sÐ,DÐ'DÑ"Eò	
ó ð
ð, U[ñ	ràÐ(Ñ(ðrð $ðrð ÐPÑQð	rð
 
# TÑ	)órðn .2ñjàÐ(Ñ(ðjð $ dÑ*ójð< .2ñoà!ðoð $ dÑ*ðoð 
ó	oð4 .2Ø!ñ	nà!ðnð $ dÑ*ðnð �d‘
ð	nð
 
ónðH .2ñsà!ðsð $ dÑ*ðsð 
ó	sðH .2ñpà!ðpð $ dÑ*ðpð 
ó	pð< .2ñ rà!ð rð $ dÑ*ð rð 
ô	 rrI   r’   )gr,  rÇ   r  ræ   r/  r¥  r¾  rW   Úcollections.abcr   r   r   r   r   Útypingr   r	   r
   r   r   r   r   r-  Úlitellm._loggingr   Úlitellm.cachingr   Úlitellm.constantsr   r   r   Ú*litellm.litellm_core_utils.litellm_loggingr   Ú*litellm.litellm_core_utils.safe_json_loadsr   Úlitellm.proxy._typesr   r   r   r   r   r   r   r   r   r   r    r!   r"   r#   Ú(litellm.proxy.db.daily_spend_bulk_upsertr$   r%   r&   Ú>litellm.proxy.db.db_transaction_queue.daily_spend_update_queuer'   Ú6litellm.proxy.db.db_transaction_queue.pod_lock_managerr(   Ú9litellm.proxy.db.db_transaction_queue.redis_update_bufferr)   Ú8litellm.proxy.db.db_transaction_queue.spend_update_queuer*   Ú:litellm.proxy.db.db_transaction_queue.tool_discovery_queuer+   Ú?litellm.proxy.db.db_transaction_queue.window_spend_update_queuer,   r-   Úlitellm.proxy.route_llm_requestr.   Ú0litellm.proxy.spend_tracking.compression_savingsr/   Ú$litellm.proxy.spend_tracking.savingsr0   r1   r2   r3   Ú3litellm.proxy.spend_tracking.spend_log_error_loggerr4   Ú%litellm.repositories.prisma_protocolsr5   Úlitellm.types.utilsr6   r¾   r7   r8   r‡   Ú	responsesÚvalueÚ
aresponsesr9   rG   r;   rL   r^   rc   rm   rs   ru   ry   rŠ   r†   r�   r’   rH   rI   rJ   ú<module>rK     sÑ  ðòó Û Û Û 	Û Û Û ß -ß 2Ñ 2ß O× OÑ Oã Ý 1Ý &÷ñ õ
 RÝ F÷÷ ÷ ÷ ÷ ñ õ
õ RÝ WÝ Uõ÷õ Cõ÷ó õ PÝ <Ý )áß>Ð>à€LØ€Lñ '0°×1DÑ1D×1JÑ1JÈI×L`ÑL`×LfÑLfÐ0gÓ&hÐ ˜eÓ hô4�(ô 4ôj˜ô jô0˜ô 0ôj˜xô jð Lð Ð5Mó ò
ôJ˜ô JðLØ Ñ$ðLà˜4‘ZðLð ˆs�^�dÑóLð.@Ø˜‘ Ñ$ð@à˜4‘Zð@ð  Ñ$ð@ð ˆ3�ˆ8�_ó	@÷&w rò w rrI   