
    sj!                       U d dl mZ d dlZd dlZd dlmZ d dlmZmZ d dlm	Z	 d dl
mZmZmZmZ d dlmZmZ d dlmZmZ  ej        e          Zd	d	d
Z e	d          Z e	d          ZdZ e	d          ZdZd dZed         Zed         Z  ed           G d d                      Z! ed           G d d                      Z" ed           G d d                      Z# ed           G d d                       Z$d! Z%i d" e# e	d#           e	d$           e	d%           e	d&          d'd(d)*          d+ e# e	d,           e	d-           e	d.           e	d/          d'd(d)*          d0 e# e	d1           e	d2           e	d3           e	d4          d'd(d)*          d5 e# e	d#           e	d6           e	d%           e	d&          d'd7d8*          d9 e# e	d:           e	d;           e	d1           e	d<          d'd=d8*          d> e# e	d?           e	d:           e	d@           e	d,          d'd7dA*          dB e# e	d#           e	d6           e	d%           e	d&          d'd7d8*          dC e# e	d#           e	d6           e	d%           e	d&          d'd7d8*          dD e# e	d#           e	d6           e	d%           e	d&          d'd7d8*          dE e# e	d#           e	d6           e	d%           e	d&          d'd7d8*          dF e# e	dG           e	d-           e	dH           e	dI          d'd7d8*          dJ e# e	dG           e	d-           e	dH           e	dI          d'd7d8*          dK e# e	d#           e	d6           e	d%           e	d&          d'd7d8*          dL e# e	dG           e	d-           e	dH           e	dI          d'd7d8*          dM e# e	d1           e	d#           e	d3           e	d4          d'd7d8*          dN e# e	d-           e	dO           e	dP           e	dQ          d'd7d8*          dR e# e	dG           e	d-           e	dH           e	dI          d'd7d8*          i dS e# e	d,           e	d:           e	d4          d'dTdUV          dW e# e	dX           e	dY           e	dZ          d'dTdUV          d[ e# e	d?           e	d\           e	d%          d'dTdUV          d] e# e	d^           e	d_           e	d3          d'dTdUV          d` e# e	d3           e	d^           e	da          d'dTdUV          db e# e	d:           e	dc           e	d,          d'dTdUV          dd e# e	de           e	df           e	dg          d'dTdUV          dh e# e	dG           e	d-           e	dH           e	dI          d'd7d8*          di e# e	dj           e	dk           e	dl           e	d1          d'd7d8*          dm e# e	d-           e	dO           e	dP           e	dQ          d'd7d8*          dn e# e	d.           e	d4           e	do           e	dH          d'd7d8*          dp e# e	dq           e	dr           e	ds          d'dtduV          dv e# e	dq           e	dr           e	ds          d'dtduV          dw e# e	dx           e	dy           e	dz          d'dtduV          d{ e# e	dq           e	dr           e	ds          d'dtduV          d| e# e	dP           e	d}           e	dX          d'd~dV          d e# e	dP           e	d           e	dX          d'ddV          i d e# e	dH           e	d,           e	do          d'd~dV          d e# e	d?           e	d           e	d@          d'ddV          d e# e	d.           e	dP           e	da          d'ddV          d e# e	d?           e	d           e	d@          d'ddV          d e# e	d%           e	dG           e	d          d'ddV          d e# e	d4           e	d:           e	d          d'ddV          d e# e	dX           e	dY           e	d          d'ddV          d e# e	d3           e	d^           e	d          d'ddV          d e# e	d#           e	d6           e	d%           e	d&          d'dd*          d e# e	d#           e	d6           e	d%           e	d&          d'dd*          d e# e	d#           e	d6           e	d%           e	d&          d'dd*          d e# e	dG           e	d-           e	dH           e	dI          d'dd*          d e# e	dG           e	d-           e	dH           e	dI          d'dd*          d e# e	dG           e	d-           e	dH           e	dI          d'dd*          d e# e	dj           e	dk           e	dl           e	d1          d'dd*          d e# e	dj           e	d          d'dd          d e# e	d           e	d          d'dd          i d e# e	d           e	dq          d'dd          d e# e	dH           e	d          d'd          d e# e	dH           e	d          d'd          d e# e	d           e	dk           e	d          d'ddV          d e# e	d           e	dk           e	d          d'ddV          d e# e	d           e	df           e	dq          d'ddV          d e# e	d           e	d           e	d          d'ddV          d e# e	dq           e	dr           e	d          d'ddV          d e# e	d^           e	d_           e	dl          d'ddV          d e# e	dH           e	d           e	d          d'ddV          d e# e	dX           e	dY           e	d          d'ddV          d e# e	d           e	dH           e	d          d'ddV          d e# e	d           e	df           e	d          d'ddV          d e# e	dH           e	d           e	d          d'ddV          d e# e	d?           e	d\           e	dH          d'ddV          d e# e	d?           e	d\           e	dH          d'ddV          d e# e	d¦           e	d\           e	dæ          d'ddV           e# e	dĦ           e	dŦ           e	dƦ          d'ddV           e# e	dǦ           e	dȦ           e	dɦ          d'ddV          dʜZ&de'd<   dD ]Z(e&de(f         e&de( dϝf<   [(dddҜ)                                D ]\  Z*Z+e&de+f         e&de*f<   [*[+ddׄZ,ddلZ-ddd݄Z.ddބZ/	 	 dddZ0ddZ1ddZ2ddZ3ddZ4d	dZ5	 	 	 d
ddZ6dddddZ7ddddddZ8	 	 	 d
ddZ9ddZ:ddZ;dS (      )annotationsN)	dataclass)datetimetimezone)Decimal)AnyDictLiteralOptional)fetch_endpoint_model_metadatafetch_model_metadata)base_url_host_matchesbase_url_hostnameg        )inputoutput01000000z)https://inference-api.nousresearch.com/v1z0.01z4subscription-included; no provider invoice for usageamountr   returnstrc                ^    | t           k    rdS | t          k     rd| d}|dk    r|ndS d| dS )u  Format a cost amount as a display label.

    Scales precision to magnitude:
    - Zero → "$0.00"
    - Sub-cent (< $0.01) → "~$0.0046" (4 dp; amounts that ROUND to
      0.0000 at 4 dp — i.e. at or below $0.00005 under banker's
      rounding — fall back to "~$<0.0001" so the label never reads
      as zero)
    - Normal → "~$1.23" (2 dp)

    This fixes #79220 where sub-cent per-turn costs on cheap models
    (DeepSeek, etc.) rendered as "$0.00" despite amount_usd carrying
    full Decimal precision.

    Shared by per-response cost labels (estimate_usage_cost) and the
    insights cost-bucket formatters — keep both surfaces on this one
    implementation so sub-cent honesty can't regress on one of them.
    z$0.00z~$z.4fz~$0.0000z	~$<0.0001.2f)_ZERO_SUBCENT_THRESHOLD)r   labels     7/home/agent/.hermes/hermes-agent/agent/usage_pricing.pyformat_cost_labelr      sU    & w"""!V!!! ++uu<    )actual	estimatedincludedunknown)provider_cost_apiprovider_generation_apiprovider_models_apiofficial_docs_snapshotuser_overridecustom_contractnoneT)frozenc                      e Zd ZU dZded<   dZded<   dZded<   dZded<   dZded<   dZ	ded	<   d
Z
ded<   edd            Zedd            ZddZd
S )CanonicalUsager   intinput_tokensoutput_tokenscache_read_tokenscache_write_tokensreasoning_tokens   request_countNzOptional[dict[str, Any]]	raw_usager   c                0    | j         | j        z   | j        z   S N)r.   r0   r1   selfs    r   prompt_tokenszCanonicalUsage.prompt_tokensS   s     4#99D<SSSr   c                     | j         | j        z   S r7   )r:   r/   r8   s    r   total_tokenszCanonicalUsage.total_tokensW   s    !D$666r   other'CanonicalUsage'c           	        t          |t                    st          S t          | j        |j        z   | j        |j        z   | j        |j        z   | j        |j        z   | j        |j        z   | j        |j        z   d          S )u0  Sum two usage buckets (e.g. MoA advisor fan-out + aggregator).

        ``raw_usage`` is dropped on the sum — it describes a single API
        response and cannot be meaningfully merged. ``request_count`` adds so
        callers can see how many underlying API calls a combined figure covers.
        N)r.   r/   r0   r1   r2   r4   r5   )	
isinstancer,   NotImplementedr.   r/   r0   r1   r2   r4   )r9   r=   s     r   __add__zCanonicalUsage.__add__[   s     %00 	"!!*U-??,u/BB"4u7NN#69QQ!2U5KK,u/BB
 
 
 	
r   )r   r-   )r=   r>   r   r>   )__name__
__module____qualname__r.   __annotations__r/   r0   r1   r2   r4   r5   propertyr:   r<   rB    r   r   r,   r,   I   s         LMM*.I....T T T XT 7 7 7 X7
 
 
 
 
 
r   r,   c                  @    e Zd ZU ded<   ded<   dZded<   dZded<   dS )	BillingRouter   providermodel base_urlr"   billing_modeN)rC   rD   rE   rF   rN   rO   rH   r   r   rJ   rJ   o   sF         MMMJJJH!L!!!!!!r   rJ   c                      e Zd ZU dZded<   dZded<   dZded<   dZded<   dZded<   dZ	d	ed
<   dZ
ded<   dZded<   dZded<   dS )PricingEntryNOptional[Decimal]input_cost_per_millionoutput_cost_per_millioncache_read_cost_per_millioncache_write_cost_per_millionrequest_costr)   
CostSourcesourceOptional[str]
source_urlpricing_versionOptional[datetime]
fetched_at)rC   rD   rE   rS   rF   rT   rU   rV   rW   rY   r[   r\   r^   rH   r   r   rQ   rQ   w   s         0444441555555999996: ::::&*L****F $J$$$$%)O))))%)J))))))r   rQ   c                  b    e Zd ZU ded<   ded<   ded<   ded<   d	Zd
ed<   d	Zded<   dZded<   d	S )
CostResultrR   
amount_usd
CostStatusstatusrX   rY   r   r   Nr]   r^   rZ   r\   rH   ztuple[str, ...]notes)rC   rD   rE   rF   r^   r\   rd   rH   r   r   r`   r`      sr         !!!!JJJ%)J))))%)O))))Er   r`   c                 >    t          j        t          j                  S r7   )r   nowr   utcrH   r   r   <lambda>rh      s    8<-- r   )openaigpt-5.6-solz5.00z30.00z0.50z6.25r&   z0https://openai.com/index/previewing-gpt-5-6-sol/zopenai-gpt-5.6-2026-07)rS   rT   rU   rV   rY   r[   r\   )ri   gpt-5.6-terraz2.50z15.00z0.25z3.125)ri   gpt-5.6-lunaz1.00z6.00z0.10z1.25)	anthropiczclaude-opus-4-8z25.00z8https://platform.claude.com/docs/en/about-claude/pricingzanthropic-pricing-2026-05)rm   zclaude-opus-4-8-fastz10.00z50.00z12.50z4https://openrouter.ai/anthropic/claude-opus-4.8-fast)rm   zclaude-sonnet-5z2.00z0.20zanthropic-pricing-2026-06-intro)rm   zclaude-opus-4-7)rm   zclaude-opus-4-7-20250507)rm   zclaude-opus-4-6)rm   zclaude-opus-4-6-20250414)rm   zclaude-sonnet-4-6z3.00z0.30z3.75)rm   zclaude-sonnet-4-6-20250414)rm   zclaude-opus-4-5)rm   zclaude-sonnet-4-5)rm   zclaude-haiku-4-5)rm   zclaude-opus-4-20250514z75.00z1.50z18.75)rm   zclaude-sonnet-4-20250514)ri   zgpt-4ozhttps://openai.com/api/pricing/zopenai-pricing-2026-03-16)rS   rT   rU   rY   r[   r\   )ri   zgpt-4o-miniz0.15z0.60z0.075)ri   zgpt-4.1z8.00)ri   zgpt-4.1-miniz0.40z1.60)ri   zgpt-4.1-nanoz0.025)ri   o3z40.00)ri   zo3-miniz1.10z4.40z0.55)rm   zclaude-3-5-sonnet-20241022)rm   zclaude-3-5-haiku-20241022z0.80z4.00z0.08)rm   zclaude-3-opus-20240229)rm   zclaude-3-haiku-20240307z0.03)deepseekzdeepseek-chatz0.14z0.28z0.0028z1https://api-docs.deepseek.com/quick_start/pricingzdeepseek-pricing-2026-07)ro   zdeepseek-reasoner)ro   deepseek-v4-proz0.435z0.87z0.003625)ro   deepseek-v4-flash)googlezgemini-3.6-flashz7.50z-https://ai.google.dev/gemini-api/docs/pricingzgoogle-pricing-2026-07-28)rr   zgemini-3.5-flashz9.00zhttps://ai.google.dev/pricingzgoogle-pricing-2026-07-07)rr   zgemini-3.5-flash-lite)rr   gemini-3.1-proz12.00)rr   gemini-3.1-flash-lite)rr   zgemini-3-pro-preview)rr   zgemini-3-flash-previewz0.05)rr   zgemini-2.5-proz0.125)rr   zgemini-2.5-flashz0.015)rr   zgemini-2.0-flash)bedrockzanthropic.claude-opus-4-8z'https://aws.amazon.com/bedrock/pricing/zanthropic-list-2026-07)ru   zanthropic.claude-opus-4-7)ru   zanthropic.claude-opus-4-6)ru   zanthropic.claude-sonnet-5zbedrock-pricing-2026-06)ru   zanthropic.claude-sonnet-4-6zbedrock-pricing-2026-04)ru   zanthropic.claude-sonnet-4-5)ru   zanthropic.claude-haiku-4-5)ru   zamazon.nova-proz3.20)rS   rT   rY   r[   r\   )ru   zamazon.nova-litez0.06z0.24)ru   zamazon.nova-microz0.035)minimaxminimax-m2.7z1.20zminimax-pricing-2026-04)rS   rT   rY   r\   )
minimax-cnrw   )	fireworksz	kimi-k2p6z0.95z0.16z,https://docs.fireworks.ai/serverless/pricingzfireworks-pricing-2026-07)ry   zkimi-k2p7-codez0.19)ry   zglm-5p2z1.40)ry   rp   z1.74z3.48z0.145)ry   rq   z0.028)ry   zqwen3p7-plus)ry   z
minimax-m3)ry   zgpt-oss-120b)ry   zgpt-oss-20bz0.07)ry   zglm-5p1z0.26)ry   zminimax-m2p7)ry   zkimi-k2p6-fast)ry   zkimi-k2p6-turbo)ry   zkimi-k2p7-code-fastz1.90z0.38z2.10z6.60z0.21z2.80z8.80z0.52))ry   zglm-5p2-fast)ry   zglm-5p1-fastz#Dict[tuple[str, str], PricingEntry]_OFFICIAL_DOCS_PRICING)rj   rk   rl   ri   z-prors   rt   )zgemini-3.1-pro-previewzgemini-3.1-flash-lite-previewrr   valuer   rR   c                f    | d S 	 t          t          |                     S # t          $ r Y d S w xY wr7   )r   r   	Exceptionr{   s    r   _to_decimalr     sG    }ts5zz"""   tts   " 
00r-   c                H    	 t          | pd          S # t          $ r Y dS w xY w)Nr   )r-   r}   r~   s    r   _to_intr     s9    5:A   qqs    
!!objnamedefaultc                z    t          | t                    r|                     ||          S t          | ||          S )a  Read a field from a usage object that may be a dict or an attribute object.

    The Responses API can return usage as either a typed SDK object (accessible
    via ``getattr``) or a plain ``dict`` (from JSON deserialisation).  Using
    ``getattr`` on a dict silently yields the default, zeroing out all token
    counts.  This helper normalises access so both shapes work transparently.
    )r@   dictgetgetattr)r   r   r   s      r   
_usage_getr   	  s<     #t &wwtW%%%3g&&&r   c                <    t          dt          |                     S )zCoerce a usage counter to a non-negative integer.

    Providers occasionally emit malformed negative counters; clamp them to 0
    so a bad field cannot corrupt session accounting (#85706).
    r   )maxr   r~   s    r   _usage_countr     s     q'%..!!!r   
model_namerK   rZ   rN   c                >   |pd                                                                 }|pd                                                                 }| pd                                 }|s%d|v r!|                    dd          \  }}|dv r|}|}|dk    rt          d||pdd          S |dk    st	          |pdd	          rt          d||pdd
          S |dk    st	          |pdd          rt          d||pt
          d
          S |dk    r.t          d|                    d          d         |pdd          S |dv r.t          d|                    d          d         |pdd          S |dv r.t          ||                    d          d         |pdd          S |dv s$t	          |pdd          st	          |pdd          r.t          d|                    d          d         |pdd          S |dk    st	          |pdd          r/t          d|                    dd          d         |pdd          S |dv s|r(t          |          dv rt          |pd||pdd          S t          |pd|r|                    d          d         nd|pdd          S )NrM   /r3   >   rr   ri   rm   zopenai-codexsubscription_included)rK   rL   rN   rO   
openrouterzopenrouter.aiofficial_models_apinouszinference-api.nousresearch.comrm   r&   >   
openai-apiri   ri   >   rv   rx   >   	vertex-aigoogle-geminigoogle-vertexgoogle-ai-studiogeminirr   vertexzaiplatform.googleapis.comz!generativelanguage.googleapis.comrr   ry   zapi.fireworks.ai>   localcustom)	localhostz	127.0.0.1r   r"   )striplowersplitrJ   r   _NOUS_DEFAULT_BASE_URLrsplitr   )r   rK   rN   provider_namebaserL   inferred_provider
bare_models           r   resolve_billing_router      s   
 ^**,,2244MN!!##))++D2$$&&E SE\\(-C(;(;%: AAA-ME&&^58>WYh  A  A  A  	A$$(=hn"o(^(^$\UWf{||||"7BHh"i"iV58CeOe  uJ  K  K  K  	K##[C8H8H8LW_Wece  uM  N  N  N  	N
 000XU[[5E5Eb5IT\Tb`b  rJ  K  K  K  	K111]%++c:J:J2:NYaYgeg  wO  P  P  P  	P 	zzz R1LMM 	{ R1TUU 	{ XU[[5E5Eb5IT\Tb`b  rJ  K  K  K  	K##'<X^M_'`'`# [S!8L8LR8P[c[igi  yQ  R  R  R  	R++++9J49P9PTn9n9n]%>heV^Vdbds|}}}}!;)[`Ch5;;sCSCSTVCWCWfhs{  tB  @B  QZ  [  [  [  [r   rL   c                h   |                                                                  }dD ]0}|                    |          r|t          |          d         } n1t	          j        dd|          }t	          j        dd|          }t	          j        dd|          }t	          j        dd|          }|S )	u  Normalize a Bedrock model id to its bare foundation-model form.

    Bedrock cross-region inference profiles prefix the foundation model id
    with a region scope (``us.`` / ``global.`` / ``eu.`` / ``apac.`` / ``au.``
    / ...), e.g. ``us.anthropic.claude-opus-4-7`` or
    ``au.anthropic.claude-sonnet-4-5-20250929-v1:0``.  The pricing table is
    keyed on the bare ``anthropic.claude-*`` id, so the prefix must be
    stripped before the lookup or every cross-region session prices as
    unknown.  Note Asia-Pacific uses ``apac.`` (a bare ``ap.`` never matches
    an ``apac.*`` id) and Australia/New Zealand use ``au.``.  Also normalizes
    dot-notation version numbers (``4.7`` → ``4-7``) and the documented
    trailing date, revision, and profile components (``-20250514-v1:0``).
    )zglobal.zus.zeu.zapac.zap.zau.zjp.zca.zsa.zme.zaf.N(\d+)\.(\d+)\1-\2z:\d+$rM   z-v\d+$z-\d{8}$r   r   
startswithlenresub)rL   r   prefixs      r   _normalize_bedrock_model_namer   R  s     ;;==  D   ??6"" 	F%DE	 6/8T22D 6(B%%D6)R&&D6*b$''DKr   c                    |                                                                  }|                    d          r|t          d          d         }t	          j        dd|          }|S )u   Normalize Anthropic model name variants to canonical form.

    Handles:
      - Dot notation: claude-opus-4.7 → claude-opus-4-7
      - Short aliases: claude-opus-4.7 → claude-opus-4-7
      - Strips anthropic/ prefix if present
    z
anthropic/Nr   r   r   )rL   r   s     r   _normalize_anthropic_model_namer   {  sc     ;;==  D|$$ (C%%&&' 6/8T22DKr   routeOptional[PricingEntry]c                   | j                                         }t                              | j        |f          }|r|S | j        dk    r:t          |          }||k    r%t                              | j        |f          }|r|S | j        dk    r:t          |          }||k    r%t                              | j        |f          }|r|S d S )Nrm   ru   )rL   r   rz   r   rK   r   r   )r   rL   entry
normalizeds       r   _lookup_official_docs_pricingr     s    KE"&&'>??E ~$$4U;;
*..
/KLLE  ~""2599
*..
/KLLE 4r   c                J    t          t                      | j        dd          S )Nz>https://openrouter.ai/docs/api/api-reference/models/get-modelszopenrouter-models-apir[   r\   )_pricing_entry_from_metadatar   rL   )r   s    r   _openrouter_pricing_entryr     s-    'S/	   r   metadataDict[str, Dict[str, Any]]model_idr[   r\   c                  || vrd S | |                              d          pi }t          |                     d                    }t          |                     d                    }t          |                     d                    }t          |                     d          p)|                     d          p|                     d                    }t          |                     d          p)|                     d	          p|                     d
                    }	|||d S dd}
t           |
|           |
|           |
|           |
|	          |d||t                      	  	        S )Npricingprompt
completionrequest
cache_readcached_promptinput_cache_readcache_writecache_creationinput_cache_writer{   rR   r   c                    | d S | t           z  S r7   )_ONE_MILLIONr~   s    r   _per_token_to_per_millionz?_pricing_entry_from_metadata.<locals>._per_token_to_per_million  s    =4|##r   r%   )	rS   rT   rU   rV   rW   rY   r[   r\   r^   )r{   rR   r   rR   )r   r   rQ   _UTC_NOW)r   r   r[   r\   r   r   r   r   r   r   r   s              r   r   r     s    xtx $$Y//52GX..//FW[[6677J'++i0011GL!! 	+;;''	+;;)** J
 M"" 	,;;'((	,;;*++ K
 ~*,t$ $ $ $
 88@@ 9 9* E E$=$=j$I$I%>%>{%K%K$'::
 
 
 
r   api_keyc                   t          | ||          }|j        dk    r)t          t          t          t          t          dd          S |j        dk    rt          |          S |j        rMt          t          |j        |pd          |j	        |j        
                    d	           d
d          }|r|S t          |          S )NrK   rN   r   r)   included-route)rS   rT   rU   rV   rY   r\   r   rM   )r   r   z/modelszopenai-compatible-models-apir   )r   rO   rQ   r   rK   r   rN   r   r   rL   rstripr   r   rK   rN   r   r   r   s         r   get_pricing_entryr     s     "*x(SSSE444#($)(-).,
 
 
 	
 ~%%(///~ ,)%.'-RPPPK.//44===:	
 
 
  	L(///r   )rK   api_moderesponse_usager   c          	     
   | st                      S |pd                                                                }|pd                                                                }|dk    s|dk    rzt          t	          | dd                    }t          t	          | dd                    }t          t	          | dd                    }t          t	          | dd                    }nz|d	k    rt          t	          | dd                    }	t          t	          | dd                    }t	          | d
d          }
t          |
rt	          |
dd          nd          }t          |
rt	          |
dd          nd          }|s"t          |
rt	          |
dd          nd          }t          d|	|z
  |z
            }nt          t	          | dd                    pt          t	          | dd                    }t          t	          | dd                    pt          t	          | dd                    }t	          | dd          }
t          |
rt	          |
dd          nd          }|st          t	          | dd                    }|st          t	          | dd                    }|st          t	          | dd                    }t          |
rt	          |
dd          nd          }|s"t          |
rt	          |
dd          nd          }|st          t	          | dd                    }|st          t	          | dd                    }t          d||z
  |z
            }d}t	          | dd          }|rt          t	          |dd                    }|s1t	          | dd          }|rt          t	          |dd                    }|dv r&|dk    r t                              d||||||           t          |||||          S )u  Normalize raw API response usage into canonical token buckets.

    Handles three API shapes:
    - Anthropic: input_tokens/output_tokens/cache_read_input_tokens/cache_creation_input_tokens
    - Codex Responses: input_tokens includes cache tokens; input_tokens_details.cached_tokens separates them
    - OpenAI Chat Completions: prompt_tokens includes cache tokens; prompt_tokens_details.cached_tokens separates them

    In both Codex and OpenAI modes, input_tokens is derived by subtracting cache
    tokens from the total — the API contract is that input/prompt totals include
    cached tokens and the details object breaks them out.
    rM   anthropic_messagesrm   r.   r   r/   cache_read_input_tokenscache_creation_input_tokenscodex_responsesinput_tokens_detailsNcached_tokensr1   cache_creation_tokensr:   completion_tokensprompt_tokens_detailsprompt_cache_hit_tokensoutput_tokens_detailsr2   completion_tokens_details>   rv   rx   u  cache_observability provider=%s mode=%s input_tokens=%s output_tokens=%s cache_read_tokens=%s cache_write_tokens=%s (note: on MiniMax-M3 cache_read carries a +128 constant floor and is not a reliable hit signal — track input_tokens drops across calls instead))r.   r/   r0   r1   r2   )r,   r   r   r   r   r   loggerdebug)r   rK   r   r   moder.   r/   r0   r1   input_totaldetailsprompt_totalr2   output_detailscompletion_detailss                  r   normalize_usager     s   "   ^**,,2244MN!!##))++D###}'C'C#J~~q$Q$QRR$ZQR%S%STT(ND]_`)a)abb)~'DaHH
 
 
"	"	"":nna#P#PQQ$ZQR%S%STT^-CTJJ(7>EJw333A
 
 *<CJJw 4a888
 
 " 	!-CJQ
7$;Q???PQ" " 1k,==@RRSS $~::
 
 I*^^QGGHH 	 %~':A>>
 
 J*^_aHHII 	 ^-DdKK )7>EJw333A
 
 ! 	 ,>+DaHH! ! ! 	 !->+DaHH! ! ! 	 !->?A>>! ! *<CJJw 4a888
 
 " 	!-"
7$A1EEE !" " " 	!->+H!LL" " " 	!->+?CC" " 1l->>ASSTT  0GNNN ['
>CUWX(Y(YZZ '8SUYZZ 	+-/A1EE    111d>R6R6R*
 4}1	
 	
 	
 !#+-)   r   rK   rN   r   usagec               
   t          | ||          }|j        dk    r t          t          ddddt          f          S t          | |||          }|st          d ddd	
          S g }t          }|j        r|j        t          d d|j        d	
          S |j	        r|j
        t          d d|j        d	
          S |j        r |j        t          d d|j        d	d          S |j        r |j        t          d d|j        d	d          S |j        '|t          |j                  |j        z  t           z  z  }|j
        '|t          |j	                  |j
        z  t           z  z  }|j        '|t          |j                  |j        z  t           z  z  }|j        '|t          |j                  |j        z  t           z  z  }|j        &|j        r|t          |j                  |j        z  z  }d}	t'          |          }
|j        dk    r)|t          k    rd}	d}
|                    t                     |j        dk    r|                    d           t          ||	|j        |
|j        |j        t1          |                    S )Nr   r   r!   r)   r   )ra   rc   rY   r   r\   rd   r   r"   zn/a)ra   rc   rY   r   )z(cache-read pricing unavailable for route)ra   rc   rY   r   rd   )z)cache-write pricing unavailable for router    r   zBOpenRouter cost is estimated from the models API until reconciled.)ra   rc   rY   r   r^   r\   rd   )r   rO   r`   r   _INCLUDED_NOTEr   r.   rS   rY   r/   rT   r0   rU   r1   rV   r   r   rW   r4   r   appendrK   r^   r\   tuple)r   r   rK   rN   r   r   r   rd   r   rc   r   s              r   estimate_usage_costr     s    "*x(SSSE444,!#
 
 
 	
 j8hX_```E YT)FRWXXXXEF _e:BT)ELX]^^^^ _u<DT)ELX]^^^^ ,4 |C     -5 |D    #/'%,--0LL|[[$0'%-..1NNQ]]](4'%122U5VVYeee)5'%233e6XX[ggg%%*=%'%-..1CCC$Ff%%E|v&E//^$$$~%%YZZZ|#-Ell   r   boolc                n    t          | ||          }|j        dk    rdS t          | |||          }|duS )u   Check whether we have pricing data for this model+route.

    Uses direct lookup instead of routing through the full estimation
    pipeline — avoids creating dummy usage objects just to check status.
    r   r   Tr   N)r   rO   r   r   s         r   has_known_pricingr     sN     "*x(SSSE444tj8hX_```Er   secondsfloatc                    | dk     r| ddS | dz  }|dk     r|ddS |dz  }|dk     r;t          |dz            }|rt          |           d| dnt          |           dS |dz  }|dd	S )
N<   .0fsm   zh h.1fd)r-   )r   minuteshoursremaining_mindayss        r   format_duration_compactr	    s    ||     lG||     bLErzzGbL))4AW#e**000000#e**GWGWGWW2:D>>>>r   c                d   t          t          |                     }|dk     rt          t          |                     S | dk     rdnd}d}|D ]`\  }}||k    rU||z  }|dk     r|d}n|dk     r|d	}n|d
}d|v r(|                    d                              d          }| | | c S a| dS )N  r   -rM   ))i ʚ;B)i@B M)r  K
   r   d   r  r   .r   ,)absr-   r   r   )r{   	abs_valuesignunits	thresholdsuffixscaledtexts           r   format_token_count_compactr    s    CJJI53u::!))33DBE" + +	6	!!*F{{ #  d{{{{3''..s33*D*&***** " <<r   )r   r   r   r   )r{   r   r   rR   )r{   r   r   r-   )r   )r   r   r   r   r   r   r   r   )NN)r   r   rK   rZ   rN   rZ   r   rJ   )rL   r   r   r   )r   rJ   r   r   )
r   r   r   r   r[   r   r\   r   r   r   )NNN)
r   r   rK   rZ   rN   rZ   r   rZ   r   r   )r   r   rK   rZ   r   rZ   r   r,   )r   r   r   r,   rK   rZ   rN   rZ   r   rZ   r   r`   )
r   r   rK   rZ   rN   rZ   r   rZ   r   r   )r   r   r   r   )r{   r-   r   r   )<
__future__r   loggingr   dataclassesr   r   r   decimalr   typingr   r	   r
   r   agent.model_metadatar   r   utilsr   r   	getLoggerrC   r   DEFAULT_PRICINGr   r   r   r   r   r   rb   rX   r,   rJ   rQ   r`   r   rz   rF   _base_56items_alias
_canonicalr   r   r   r   r   r   r   r   r   r   r   r   r   r   r	  r  rH   r   r   <module>r*     sQ   " " " " " " "  				 ! ! ! ! ! ! ' ' ' ' ' ' ' '       / / / / / / / / / / / / T T T T T T T T : : : : : : : :		8	$	$3//wy!!D  WV__  H   > AB

 $"
 "
 "
 "
 "
 "
 "
 "
J $" " " " " " " " $	* 	* 	* 	* 	* 	* 	* 	* $                .-
M? |&wv ' 0 0$+GFOO%,WV__'E0  !M?2 |&wv ' 0 0$+GFOO%,WW%5%5'E0  9M?J |&wv '$+GFOO%,WV__'E0  QM?j |&wv ' 0 0$+GFOO%,WV__'M3  qM?B |&ww// ' 0 0$+GFOO%,WW%5%5'I3  IM?d |&wv ' 0 0$+GFOO%,WV__'M9  kM?D |&wv ' 0 0$+GFOO%,WV__'M3  KM?\ |&wv ' 0 0$+GFOO%,WV__'M3  cM?v |&wv ' 0 0$+GFOO%,WV__'M3  }M?N |&wv ' 0 0$+GFOO%,WV__'M3  UM?f |&wv ' 0 0$+GFOO%,WV__'M3  mM?~ |&wv ' 0 0$+GFOO%,WV__'M3  EM?X |&wv ' 0 0$+GFOO%,WV__'M3  _M?p |&wv ' 0 0$+GFOO%,WV__'M3  wM?H |&wv '$+GFOO%,WV__'M3  OM?b |&ww// ' 0 0$+GFOO%,WW%5%5'M3  iM?z |&wv ' 0 0$+GFOO%,WV__'M3  AM? M?T |&wv ' 0 0$+GFOO'43  [M?j |&wv '$+GG$4$4'43  qM?@ |&wv '$+GFOO'43  GM?V |&wv '$+GFOO'43  ]M?l |&wv '$+GG$4$4'43  sM?B	 |&ww// ' 0 0$+GFOO'43  I	M?X	 |&wv '$+GFOO'43  _	M?p	 |&wv ' 0 0$+GFOO%,WV__'M3  w	M?H
 |&wv '$+GFOO%,WV__'M3  O
M?`
 |&ww// ' 0 0$+GFOO%,WW%5%5'M3  g
M?x
 |&wv '$+GFOO%,WV__'M3  
M?X |&wv '$+GH$5$5'F2  _M?n |&wv '$+GH$5$5'F2  uM?D |&ww// '$+GJ$7$7'F2  KM?Z |&wv '$+GH$5$5'F2  aM?r |&wv '$+GFOO'B3  yM?H |&wv '$+GFOO'23  OM? M? M?^ |&wv '$+GFOO'B3  eM?t |&wv ' 0 0$+GFOO'23  {M?J |&wv '$+GG$4$4'23  QM?` |&wv ' 0 0$+GFOO'23  gM?v |&wv '$+GFOO'23  }M?L |&wv ' 0 0$+GG$4$4'23  SM?b |&wv '$+GG$4$4'23  iM?x |&wv '$+GFOO'23  M?b |&wv ' 0 0$+GFOO%,WV__'<0  iM?z |&wv ' 0 0$+GFOO%,WV__'<0  AM?R |&wv ' 0 0$+GFOO%,WV__'<0  YM?j |&wv ' 0 0$+GFOO%,WV__'<1  qM?B |&wv ' 0 0$+GFOO%,WV__'<1  IM?Z |&wv ' 0 0$+GFOO%,WV__'<1  aM?r |&wv '$+GFOO%,WV__'<1  yM?J |&wv ''<1  QM?^ |&wv ''<1  eM? M? M?r |&ww// ''<1  yM?H |&wv ''1	  OM?Z |&wv ''1	  aM?v |&wv '$+GFOO'A3  }M?L |&wv '$+GFOO'A3  SM?b |&wv '$+GFOO'A3  iM?x |&wv '$+GG$4$4'A3  M?N |&wv '$+GG$4$4'A3  UM?d |&wv '$+GFOO'A3  kM?z |&wv '$+GFOO'A3  AM?P |&wv '$+GG$4$4'A3  WM?f |&wv '$+GG$4$4'A3  mM?| |&wv '$+GFOO'A3  CM?R |&wv '$+GFOO'A3  YM?l |&wv '$+GFOO'A3  sM?B |&wv '$+GFOO'A3  IM?X |&wv '$+GFOO'A3  _M? M?t |&wv '$+GFOO'A3   |&wv '$+GFOO'A3  KM? M? M?  M M M Md A  H<R	8=H&7&7&7899  /%<  %'' FJ 2H	:2Hf-.. J      
' 
' 
' 
' 
'" " " " #"/[ /[ /[ /[ /[d& & & &R   "   0   ) ) ) )\ #"!	0 0 0 0 0B #"	X X X X X X~ #"!N N N N N Nf #"!	    &        r   