Ë
    tPêj/  ã            	       ó´  — U d 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mZmZmZmZ ddlmZ ddlmZ  G d	„ d
ee«      Ze G d„ de
«      «       Ze G d„ de
«      «       ZdZe	ed<   dZe	eedf      ed<   dZe	eedf      ed<    edh«      Z e	ed<    ed„ ejB                  jD                  D «       «      Z#e	eedf      ed<   dededz  fd„Z$dZ%e	ed<    ejL                  d«      Z'e	ed <   d!Z(e	ed"<   d#Z)e	ed$<   d%Z*e	eedf      ed&<   dededz  fd'„Z+dededz  fd(„Z,d/ded)edeeef   dz  fd*„Z-d+eee.e.f      dedz  fd,„Z/ G d-„ d.«      Z0y)0aÕ  
Counts HTTP requests to LLM inference, MCP, and A2A endpoints.

Feeds two independent sinks off one classification:

- ``GatewayRequestSink`` receives every classified request with its status and
  is the source of truth for SGR (successful gateway requests) on the admin UI.
  Not license-gated (see litellm.proxy.db.gateway_request_tracking). It is not
  told which deployment served the request: it persists its counts, so every
  dimension it takes has to be one the proxy chooses.
- ``BillingRecorder`` receives 2xx requests only and exports them for
  enterprise metering (see litellm.proxy.enterprise_billing.billing_metrics).

Both are injected. When neither is present the middleware is a transparent
pass-through.
é    N)ÚCallableÚSequence)ÚEnum)ÚFinalÚProtocolÚruntime_checkable)ÚASGIAppÚMessageÚReceiveÚScopeÚSend)Úverbose_proxy_logger)ÚLiteLLMRoutesc                   ó   — e Zd ZdZdZdZy)ÚBillableCategoryÚllmÚmcpÚa2aN)Ú__name__Ú
__module__Ú__qualname__ÚLLMÚMCPÚA2A© ó    ú�/home/oem/CyberBrain26-unified/.venv/lib/python3.12/site-packages/litellm/proxy/middleware/billable_request_metrics_middleware.pyr   r      s   „ Ø
€CØ
€CØ
�Cr   r   c            
       ó.   — e Zd Zdededededz  ddf
d„Zy)ÚBillingRecorderÚcategoryÚrouteÚstatus_codeÚmodel_idNÚreturnc                 ó   — y ©Nr   )Úselfr    r!   r"   r#   s        r   ÚrecordzBillingRecorder.record&   ó   � r   )r   r   r   r   ÚstrÚintr(   r   r   r   r   r   $   s'   „ àtÐ"2Ðt¸3ÐtÈSÐtÐ\_ÐbfÑ\fÐtÐkoÔtr   r   c                   ó(   — e Zd ZdZdedededdfd„Zy)ÚGatewayRequestSinka¹  
    Records every classified request, 2xx or not, for the SGR dashboard.

    Distinct from BillingRecorder on three counts: this is not license-gated,
    it is not restricted to 2xx, and it takes no model id. The deployment that
    served a request is deliberately not part of what it records, because the
    dashboard aggregates by route and a per-deployment dimension would only
    multiply the rows it has to sum back together.
    r    r!   r"   r$   Nc                 ó   — y r&   r   )r'   r    r!   r"   s       r   r(   zGatewayRequestSink.record5   r)   r   )r   r   r   Ú__doc__r   r*   r+   r(   r   r   r   r-   r-   )   s#   „ ñð _Ð"2Ð^¸3Ð^ÈSÐ^ÐUYÔ^r   r-   s   x-litellm-model-idÚ_MODEL_ID_HEADER)z/chat/completionsz/completionsz/embeddingsz
/responsesz/rerankz/moderationsz/images/generationsz/images/editsz/images/variationsz/audio/transcriptionsz/audio/translationsz/audio/speechz/videosz/remixz/ocrz/searchz
/rag/queryz/rag/ingestz:generateContentz:streamGenerateContent.Ú_LLM_ROUTE_SUFFIXES)z/v1/messagesz/interactionsz/v1beta/interactionsz/comprehendmedicalÚ_LLM_ROUTE_EXACTz	/langfuseÚ"_NON_BILLABLE_PASSTHROUGH_PREFIXESc              #   ó0   K  — | ]  }|t         vr|–— Œ y ­wr&   )r3   )Ú.0Úprefixs     r   ú	<genexpr>r7   h   s!   è ø€ ò 6àØÔ7Ñ7ô ñ6ùs   ‚Ú_PASSTHROUGH_PREFIXESÚpathr$   c                 óª   ‡ — t        ˆ fd„t        D «       d «      }|�|S t        ˆ fd„t        D «       d «      }|�|S t        ˆ fd„t        D «       d «      S )Nc              3   ó.   •K  — | ]  }‰|k(  sŒ	|–— Œ y ­wr&   r   )r5   r!   r9   s     €r   r7   z&_classify_llm_route.<locals>.<genexpr>p   s   øè ø€ ÒT¨ÀdÈeÃmœuÑTùs   ƒ
Žc              3   óP   •K  — | ]  }‰|k(  s‰j                  |«      sŒ|–— Œ y ­wr&   )Úendswith)r5   Úsuffixr9   s     €r   r7   z&_classify_llm_route.<locals>.<genexpr>s   s&   øè ø€ Òm FÀTÈVÂ^ÐW[×WdÑWdÐekÕWlœÑmùs   ƒ&Ÿ&c              3   óL   •K  — | ]  }‰j                  |› d �«      sŒ|–— Œ y­w)ú/N©Ú
startswith©r5   r6   r9   s     €r   r7   z&_classify_llm_route.<locals>.<genexpr>w   s%   øè ø€ Ò]˜F¸t¿¹ÐRXÐQYÐYZÈ|Õ?\”Ñ]ùs   ƒ$�$)Únextr2   r1   r8   )r9   Úexact_matchÚsuffix_matchs   `  r   Ú_classify_llm_routerG   o   sX   ø€ ÜÓTÔ2BÔTÐVZÓ[€KØÐØÐÜÓmÔ.AÔmÐosÓt€LØÐØÐäÓ]Ô&;Ô]Ð_cÓdÐdr   z/v1/mcpÚ_MCP_MANAGEMENT_PREFIXz/(?:toolset/)?[^/]+/mcpÚ_MCP_DYNAMIC_TRANSPORTz/mcp-rest/tools/callÚ_MCP_REST_TOOL_CALLz/message/sendÚ_A2A_INVOKE_SUFFIX)z/v1/a2a/z/a2a/Ú_A2A_TRANSPORT_PREFIXESc                 ó¶   — | t         k(  s| j                  t         › d�«      ry | dk(  s| j                  d«      ry| t        k(  ryt        j	                  | «      �yy )Nr@   z/mcpz/mcp/)rH   rB   rJ   rI   Ú	fullmatch©r9   s    r   Ú_classify_mcp_routerP   Œ   s[   € ØÔ%Ò%¨¯©Ô<RÐ;SÐSTÐ9UÔ)VØØˆv‚~˜Ÿ™¨Ô1ØØÔ"Ò"ØÜ×'Ñ'¨Ó-Ð9ØØr   c                 ób   ‡ — ‰ j                  t        «      rt        ˆ fd„t        D «       «      ryy )Nc              3   ó@   •K  — | ]  }‰j                  |«      –— Œ y ­wr&   rA   rC   s     €r   r7   z&_classify_a2a_route.<locals>.<genexpr>™   s   øè ø€ Ò0oÈV°·±À×1HÑ0oùs   ƒz/a2a)r=   rK   ÚanyrL   rO   s   `r   Ú_classify_a2a_routerT   ˜   s$   ø€ Ø‡}�}Ô'Ô(¬SÓ0oÔWnÔ0oÔ-oØØr   Úmethodc                 ó  — | j                  d«      xs d}t        |«      }|�t        j                  |fS t	        |«      }|�t        j
                  |fS |j                  «       dk7  ryt        |«      }|�t        j                  |fS y)zPMap a request path to its (category, normalized route), or None if not billable.r@   NÚPOST)	ÚrstriprP   r   r   rT   r   ÚupperrG   r   )r9   rU   Ú
normalizedÚ	mcp_routeÚ	a2a_routeÚ	llm_routes         r   Úclassify_billable_requestr^   ž   sŽ   € àŸ™ CÓ(Ò/¨C€Jä*¨:Ó6€IØÐÜ ×$Ñ$ iÐ0Ð0ä*¨:Ó6€IØÐÜ ×$Ñ$ iÐ0Ð0ð
 ‡|�|ƒ~˜ÒØä*¨:Ó6€IØÐÜ ×$Ñ$ iÐ0Ð0Ør   Úheadersc                 ó(   — t        d„ | D «       d «      S )Nc              3   óz   K  — | ]3  \  }}|j                  «       t        k(  sŒ|sŒ!|j                  d «      –— Œ5 y­w)zlatin-1N)Úlowerr0   Údecode)r5   ÚnameÚvalues      r   r7   z$_extract_model_id.<locals>.<genexpr>¸   s.   è ø€ Òj¡[ T¨5¸t¿z¹z»|ÔO_Ó?_Òdiˆ�‰�i×	 Ñjùs   ‚;¢;¥;)rD   )r_   s    r   Ú_extract_model_idrf   ¶   s   € ÜÙj°GÔjØóð r   c                   ó®   — e Zd ZdZ	 	 	 	 ddededz  deg edz  f   dz  dedz  deg edz  f   dz  ddfd	„Zdedz  fd
„Z	dedz  fd„Z
dedededdfd„Zy)Ú BillableRequestMetricsMiddlewarean  
    Pure ASGI middleware that classifies each request once and fans the result
    out to the SGR sink (any status) and the billing recorder (2xx only).
    Modeled on InFlightRequestsMiddleware: it wraps `send`, reads the final
    status and the x-litellm-model-id header off the `http.response.start`
    message, and never blocks or fails the request path.
    NÚappÚrecorderÚrecorder_factoryÚsinkÚsink_factoryr$   c                 óÒ   — || _         || _        || _        |d u | _        t	        j
                  «       | _        || _        || _        |d u | _	        t	        j
                  «       | _
        y r&   )ri   rj   Ú_recorder_factoryÚ	_resolvedÚ	threadingÚLockÚ_resolve_lockrl   Ú_sink_factoryÚ_sink_resolvedÚ_sink_resolve_lock)r'   ri   rj   rk   rl   rm   s         r   Ú__init__z)BillableRequestMetricsMiddleware.__init__Æ   sd   € ð ˆŒØ ˆŒð "2ˆÔØ)¨TÐ1ˆŒÜ&Ÿ^™^Ó-ˆÔð ˆŒ	Ø)ˆÔØ*¨dÐ2ˆÔÜ"+§.¡.Ó"2ˆÕr   c                 ó  — | j                   r| j                  S | j                  5  | j                   s-| j                  }|� |«       n| j                  | _        d| _         d d d «       | j                  S # 1 sw Y   | j                  S xY w©NT)rp   rj   rs   ro   ©r'   Úfactorys     r   Ú_resolve_recorderz2BillableRequestMetricsMiddleware._resolve_recorderß   ss   € Ø�>Š>Ø—=‘=Ð ð ×Ññ 	&Ø—>’>Ø!%×!7Ñ!7�Ø-4Ð-@¡¤	ÀdÇmÁm�”Ø!%�”÷		&ð
 �}‰}Ð÷	&ð
 �}‰}Ðúó   ¥:A3Á3Bc                 ó  — | j                   r| j                  S | j                  5  | j                   s-| j                  }|� |«       n| j                  | _        d| _         d d d «       | j                  S # 1 sw Y   | j                  S xY wry   )ru   rl   rv   rt   rz   s     r   Ú_resolve_sinkz.BillableRequestMetricsMiddleware._resolve_sinkë   sv   € Ø×ÒØ—9‘9ÐØ×$Ñ$ñ 	+Ø×&Ò&Ø!%×!3Ñ!3�Ø)0Ð)<™GœIÀ$Ç)Á)�”	Ø&*�Ô#÷		+ð
 �y‰yÐ÷	+ð
 �y‰yÐúr}   ÚscopeÚreceiveÚsendc              ƒ   ó  ‡‡
‡K  — |d   dk7  r| j                  ||‰«      ƒ d {  –—†  y | j                  «       }| j                  «       }|€|€| j                  ||‰«      ƒ d {  –—†  y t        |j	                  dd«      |j	                  dd«      «      }|€| j                  ||‰«      ƒ d {  –—†  y |\  }}dŠd Š
dt
        d	d fˆ
ˆˆfd
„}	| j                  |||	«      ƒ d {  –—†  |�	 |j                  ||‰¬«       |�&d‰cxk  rdk  rn y 	 |j                  ||‰‰
¬«       y y y 7 �Œ7 ŒÆ7 Œ~7 ŒK# t        $ r t        j                  d|d¬«       Y ŒUw xY w# t        $ r t        j                  d|d¬«       Y y w xY w­w)NÚtypeÚhttpr9   Ú rU   rW   r   Úmessager$   c              “   ó‚   •K  — | d   dk(  r | d   Št        | j                  dg «      «      Š ‰| «      ƒ d {  –—†  y 7 Œ­w)Nr„   zhttp.response.startÚstatusr_   )rf   Úget)r‡   r#   r‚   r"   s    €€€r   Úsend_wrapperz?BillableRequestMetricsMiddleware.__call__.<locals>.send_wrapper	  s@   øè ø€ à�v‰Ð"7Ò7Ø% hÑ/�Ü,¨W¯[©[¸ÀBÓ-GÓH�Ù�w“-×Òús   ƒ4?·=¸?)r    r!   r"   z&gateway request metering failed for %sT)Úexc_infoéÈ   i,  )r    r!   r"   r#   z'billable request metering failed for %s)
ri   r|   r   r^   rŠ   r
   r(   Ú	Exceptionr   Úwarning)r'   r€   r�   r‚   rj   rl   Úclassificationr    r!   r‹   r#   r"   s      `      @@r   Ú__call__z)BillableRequestMetricsMiddleware.__call__õ   sª  úè ø€ Ø�‰=˜FÒ"Ø—(‘(˜5 '¨4Ó0×0Ð0Øà×0Ñ0Ó2ˆØ×(Ñ(Ó*ˆØÐ  Ø—(‘(˜5 '¨4Ó0×0Ð0Øä 9¸%¿)¹)ÀFÈBÓ:OÐQV×QZÑQZÐ[cÐekÓQlÓ mˆØÐ!Ø—(‘(˜5 '¨4Ó0×0Ð0Øà(‰ˆ�%ØˆØ#ˆð	 ¬ð 	 °D÷ 	 ð �h‰h�u˜g |Ó4×4Ð4àÐðmØ—‘ X°UÈ�ÔTð Ð C¨;Ô$<¸Õ$<ðnØ—‘¨¸ÈKÐbj�Õkð %=ÐðC 1ùð 1øð
 1øð 	5ùô
 ò mÜ$×,Ñ,Ð-UÐW\Ðgk×lðmûô ò nÜ$×,Ñ,Ð-VÐX]Ðhl×mðnüsŽ   …E?¤D(¥?E?Á$D+Á%A	E?Â.D-Â/4E?Ã#D/Ã$E?Ã+D1 Ã?E?ÄE Ä%E?Ä+E?Ä-E?Ä/E?Ä1!EÅE?ÅEÅE?Å!E<Å9E?Å;E<Å<E?)NNNN)r   r   r   r/   r	   r   r   r-   rw   r|   r   r   r   r   r‘   r   r   r   rh   rh   ½   sÐ   „ ñð ,0ØHLØ*.ØGKñ3àð3ð " DÑ(ð3ð # 2 ¸Ñ'=Ð#=Ñ>ÀÑEð	3ð
 ! 4Ñ'ð3ð ˜rÐ#5¸Ñ#<Ð<Ñ=ÀÑDð3ð 
ó3ð2
 ?°TÑ#9ó 
ðÐ1°DÑ8ó ð'n Eð 'n°Gð 'nÀ4ð 'nÈDô 'nr   rh   )rW   )1r/   Úrerq   Úcollections.abcr   r   Úenumr   Útypingr   r   r   Ústarlette.typesr	   r
   r   r   r   Úlitellm._loggingr   Úlitellm.proxy._typesr   r*   r   r   r-   r0   Ú__annotations__r1   Útupler2   Ú	frozensetr3   Úmapped_pass_through_routesre   r8   rG   rH   ÚcompilerI   rJ   rK   rL   rP   rT   r^   Úbytesrf   rh   r   r   r   ú<module>rŸ      s   ðòó" 
Û ß .Ý ß 5Ñ 5ç BÕ Bå 1Ý .ô�s˜Dô ð ôu�hó uó ðuð ô_˜ó _ó ð_ð 0Ð �%Ó /ð/Ð �U˜5  c ™?Ñ+ó ð4,Ð �%˜˜c 3˜h™Ñ(ó ñ -6°{°mÓ,DÐ " EÓ DÙ05ñ 6à×:Ñ:×@Ñ@ô6ó 1Ð �u˜U 3¨ 8™_Ñ-ó ðe˜cð e c¨D¡jó eð !*Ð ˜Ó )Ø * §
¡
Ð+EÓ FÐ ˜Ó Fð 4Ð �UÓ 3à+Ð �EÓ +Ø2GÐ ˜˜u S¨# X™Ñ/Ó Gð	˜cð 	 c¨D¡jó 	ð˜cð  c¨D¡jó ñ Cð °ð À%ÐHXÐZ]ÐH]ÑB^ÐaeÑBeó ð0˜x¨¨e°U¨lÑ(;Ñ<ð ÀÀtÁó ÷_nò _nr   