
    i%a                    
   U d dl mZ d dlmZ d dlmZmZ d dlmZ d dlm	Z	m
Z
mZmZ d dlmZmZ dddZ ed	          Z e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           d% e ed&           ed'           ed(          dd)d*+          d, e ed-           ed.           ed/          dd)d*+          d0 e ed1           ed2           ed3          dd)d*+          d4 e ed5           ed6           ed7          dd)d*+          d8 e ed7           ed5           ed9          dd)d*+          d: e ed'           ed;           ed&          dd)d*+          d< e ed=           ed>           ed?          dd)d*+          d@ e ed"           ed           ed#           ed$          dddA           dB e edC           edD           edE           edF          dddA           dG e ed           ed           ed           ed          dddA           dH e edI           ed(           edJ           ed#          dddA           dK e edL           edM          ddNdOP          dQ e ed?           edR          ddNdOP          dS e ed(           ed'          ddTdUP          dV e ed-           ed.          ddTdUP           e ed7           ed5          ddTdUP           e ed           ed          ddWdXP           e ed"           ed          ddWdXP           e ed"           ed          ddWdXP           e edC           edD          ddWdXP           e edC           edY          ddWdXP           e edZ           ed[          ddWdXP           e ed\           edL          ddWdXP          d]Zd^ed_<   dddZddfZ	 	 dddmZddpZddqZ ddwZ!	 	 	 dddyZ"dgdgdzdd}Z#dgdgdgd~ddZ$	 	 	 dddZ%ddZ&ddZ'dgS )    )annotations)	dataclass)datetimetimezone)Decimal)AnyDictLiteralOptional)fetch_endpoint_model_metadatafetch_model_metadatag        )inputoutput01000000)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
S )CanonicalUsager   intinput_tokensoutput_tokenscache_read_tokenscache_write_tokensreasoning_tokens   request_countNzOptional[dict[str, Any]]	raw_usagereturnc                0    | j         | j        z   | j        z   S N)r!   r#   r$   selfs    ;/home/agentuser/.hermes/hermes-agent/agent/usage_pricing.pyprompt_tokenszCanonicalUsage.prompt_tokens%   s     4#99D<SSS    c                     | j         | j        z   S r+   )r/   r"   r,   s    r.   total_tokenszCanonicalUsage.total_tokens)   s    !D$666r0   )r)   r    )__name__
__module____qualname__r!   __annotations__r"   r#   r$   r%   r'   r(   propertyr/   r2    r0   r.   r   r      s         LMM*.I....T T T XT 7 7 7 X7 7 7r0   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 )	BillingRoutestrprovidermodel base_urlr   billing_modeN)r3   r4   r5   r6   r?   r@   r8   r0   r.   r:   r:   .   sF         MMMJJJH!L!!!!!!r0   r:   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)r3   r4   r5   rD   r6   rE   rF   rG   rH   rJ   rL   rM   rO   r8   r0   r.   rB   rB   6   s         0444441555555999996: ::::&*L****F $J$$$$%)O))))%)J))))))r0   rB   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 )
CostResultrC   
amount_usd
CostStatusstatusrI   rJ   r;   labelNrN   rO   rK   rM   r8   ztuple[str, ...]notes)r3   r4   r5   r6   rO   rM   rV   r8   r0   r.   rQ   rQ   C   sr         !!!!JJJ%)J))))%)O))))Er0   rQ   c                 >    t          j        t          j                  S r+   )r   nowr   utcr8   r0   r.   <lambda>rZ   N   s    8<-- r0   )	anthropiczclaude-opus-4-20250514z15.00z75.00z1.50z18.75r   zChttps://docs.anthropic.com/en/docs/build-with-claude/prompt-cachingz#anthropic-prompt-caching-2026-03-16)rD   rE   rF   rG   rJ   rL   rM   )r[   zclaude-sonnet-4-20250514z3.00z0.30z3.75)openaizgpt-4oz2.50z10.00z1.25zhttps://openai.com/api/pricing/zopenai-pricing-2026-03-16)rD   rE   rF   rJ   rL   rM   )r\   zgpt-4o-miniz0.15z0.60z0.075)r\   zgpt-4.1z2.00z8.00z0.50)r\   zgpt-4.1-miniz0.40z1.60z0.10)r\   zgpt-4.1-nanoz0.025)r\   o3z40.00)r\   zo3-miniz1.10z4.40z0.55)r[   zclaude-3-5-sonnet-20241022zanthropic-pricing-2026-03-16)r[   zclaude-3-5-haiku-20241022z0.80z4.00z0.08z1.00)r[   zclaude-3-opus-20240229)r[   zclaude-3-haiku-20240307z0.25z0.03)deepseekzdeepseek-chatz0.14z0.28z1https://api-docs.deepseek.com/quick_start/pricingzdeepseek-pricing-2026-03-16)rD   rE   rJ   rL   rM   )r^   zdeepseek-reasonerz2.19)googlezgemini-2.5-prozhttps://ai.google.dev/pricingzgoogle-pricing-2026-03-16)r_   zgemini-2.5-flashz'https://aws.amazon.com/bedrock/pricing/zbedrock-pricing-2026-04z3.20z0.06z0.24z0.035))r_   zgemini-2.0-flash)bedrockzanthropic.claude-opus-4-6)r`   zanthropic.claude-sonnet-4-6)r`   zanthropic.claude-sonnet-4-5)r`   zanthropic.claude-haiku-4-5)r`   zamazon.nova-pro)r`   zamazon.nova-lite)r`   zamazon.nova-microz#Dict[tuple[str, str], PricingEntry]_OFFICIAL_DOCS_PRICINGvaluer   r)   rC   c                f    | d S 	 t          t          |                     S # t          $ r Y d S w xY wr+   )r   r;   	Exceptionrb   s    r.   _to_decimalrf   l  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    rd   re   s    r.   _to_intrh   u  s9    5:A   qqs    
!!N
model_namer;   r<   rK   r?   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d	|v rt          d||pdd
          S |dk    r.t          d|                    d          d         |pdd          S |dk    r.t          d|                    d          d         |pdd          S |dv s|rd|v rt          |pd||pdd          S t          |pd|r|                    d          d         nd|pdd          S )Nr>   /r&   >   r_   r\   r[   zopenai-codexsubscription_included)r<   r=   r?   r@   
openrouterzopenrouter.aiofficial_models_apir[   r   r\   >   localcustom	localhostrq   r   )striplowersplitr:   )ri   r<   r?   provider_namebaser=   inferred_provider
bare_models           r.   resolve_billing_routerz   |  s0   
 ^**,,2244MN!!##))++D2$$&&E SE\\(-C(;(;%: AAA-ME&&^58>WYh  A  A  A  	A$$4(?(?\UWf{||||##[C8H8H8LW_Wece  uM  N  N  N  	N  XU[[5E5Eb5IT\Tb`b  rJ  K  K  K  	K++++9L9L]%>heV^Vdbds|}}}}!;)[`Ch5;;sCSCSTVCWCWfhs{  tB  @B  QZ  [  [  [  [r0   routeOptional[PricingEntry]c                r    t                               | j        | j                                        f          S r+   )ra   getr<   r=   rt   r{   s    r.   _lookup_official_docs_pricingr     s+    !%%u~u{7H7H7J7J&KLLLr0   c                J    t          t                      | j        dd          S )Nz>https://openrouter.ai/docs/api/api-reference/models/get-modelszopenrouter-models-apirL   rM   )_pricing_entry_from_metadatar   r=   r   s    r.   _openrouter_pricing_entryr     s-    'S/	   r0   metadataDict[str, Dict[str, Any]]model_idrL   rM   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_writerb   rC   r)   c                    | d S | t           z  S r+   )_ONE_MILLIONre   s    r.   _per_token_to_per_millionz?_pricing_entry_from_metadata.<locals>._per_token_to_per_million  s    =4|##r0   r   )	rD   rE   rF   rG   rH   rJ   rL   rM   rO   )rb   rC   r)   rC   )r~   rf   rB   _UTC_NOW)r   r   rL   rM   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$'::
 
 
 
r0   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r<   r?   rl   r   included-route)rD   rE   rF   rG   rJ   rM   rm   r>   )r   rk   z/modelszopenai-compatible-models-apir   )rz   r@   rB   _ZEROr<   r   r?   r   r   r=   rstripr   ri   r<   r?   r   r{   entrys         r.   get_pricing_entryr     s     "*x(SSSE444#($)(-).,
 
 
 	
 ~%%(///~ ,)%.'-RPPPK.//44===:	
 
 
  	L(///r0   )r<   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                    }nU|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          }t          d|	|z
  |z
            }nt          t	          | dd                    }t          t	          | dd                    }t	          | dd          }
t          |
rt	          |
dd          nd          }t          |
rt	          |
dd          nd          }t          d||z
  |z
            }d}t	          | dd          }|rt          t	          |d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.
    r>   anthropic_messagesr[   r!   r   r"   cache_read_input_tokenscache_creation_input_tokenscodex_responsesinput_tokens_detailsNcached_tokenscache_creation_tokensr/   completion_tokensprompt_tokens_detailsr$   output_tokens_detailsr%   )r!   r"   r#   r$   r%   )r   rs   rt   rh   getattrmax)r   r<   r   rv   moder!   r"   r#   r$   input_totaldetailsprompt_totalr%   output_detailss                 r.   normalize_usager     s   "   ^**,,2244MN!!##))++D###}'C'Cw~~qIIJJ K KLL#GN<UWX$Y$YZZ$W^=Z\]%^%^__	"	"	"gnnaHHII K KLL.*@$GG#G$ZGG_a$H$H$HYZ[[$<CJGG4a888
 
 1k,==@RRSSw~JJKK8KQ O OPP.*A4HH#G$ZGG_a$H$H$HYZ[[$9@GGG11555a
 
 1l->>ASSTT^-DdKKN S"7>;Mq#Q#QRR!#+-)   r0   r<   r?   r   usagec                  t          | ||          }|j        dk    rt          t          dddd          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}	d|d}
|j        dk    r|t          k    rd}	d}
|j        dk    r|                    d           t          ||	|j        |
|j        |j        t-          |                    S )Nr   rl   r   r   r   )rR   rT   rJ   rU   rM   r   r   zn/a)rR   rT   rJ   rU   )z(cache-read pricing unavailable for route)rR   rT   rJ   rU   rV   )z)cache-write pricing unavailable for router   z~$.2frm   zBOpenRouter cost is estimated from the models API until reconciled.)rR   rT   rJ   rU   rO   rM   rV   )rz   r@   rQ   r   r   r!   rD   rJ   r"   rE   r#   rF   r$   rG   r   r   rH   r'   r<   appendrO   rM   tuple)ri   r   r<   r?   r   r{   r   rV   amountrT   rU   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E|v&E//~%%YZZZ|#-Ell   r0   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   rl   Tr   N)rz   r@   r   r   s         r.   has_known_pricingr   z  sN     "*x(SSSE444tj8hX_```Er0   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>>>>r0   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   -r>   ))i ʚ;B)i@B M)r   K
   r   d   r   r   .r   ,)absr    r;   r   )rb   	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*&***** " <<r0   )rb   r   r)   rC   )rb   r   r)   r    )NN)ri   r;   r<   rK   r?   rK   r)   r:   )r{   r:   r)   r|   )
r   r   r   r;   rL   r;   rM   r;   r)   r|   )NNN)
ri   r;   r<   rK   r?   rK   r   rK   r)   r|   )r   r   r<   rK   r   rK   r)   r   )ri   r;   r   r   r<   rK   r?   rK   r   rK   r)   rQ   )
ri   r;   r<   rK   r?   rK   r   rK   r)   r   )r   r   r)   r;   )rb   r    r)   r;   )(
__future__r   dataclassesr   r   r   decimalr   typingr   r	   r
   r   agent.model_metadatar   r   DEFAULT_PRICINGr   r   rS   rI   r   r:   rB   rQ   r   ra   r6   rf   rh   rz   r   r   r   r   r   r   r   r   r   r8   r0   r.   <module>r      sy
   " " " " " " " ! ! ! ! ! ! ' ' ' ' ' ' ' '       / / / / / / / / / / / / T T T T T T T T3//wy!!AB

 $7 7 7 7 7 7 7 7$ $" " " " " " " " $	* 	* 	* 	* 	* 	* 	* 	* $                .-
V? |&ww// ' 0 0$+GFOO%,WW%5%5'X=  	V? |&wv ' 0 0$+GFOO%,WV__'X=  !V?4 |&wv ' 0 0$+GFOO'43  ;V?J |&wv '$+GG$4$4'43  QV?` |&wv '$+GFOO'43  gV?v |&wv '$+GFOO'43  }V?L |&wv '$+GG$4$4'43  SV?b |&ww// ' 0 0$+GFOO'43  iV?x |&wv '$+GFOO'43  V?P |&wv ' 0 0$+GFOO%,WV__'X6  WV?h |&wv '$+GFOO%,WV__'X6  oV?@ |&ww// ' 0 0$+GFOO%,WW%5%5'X6  GV?X |&wv '$+GFOO%,WV__'X6  _V?r |&wv ''F5  yV?F |&wv ''F5  MV?\ |&wv ' 0 0'23  cV?p |&wv ''23  wV?J |&wv ''23   |&ww// ' 0 0'<1   |&wv ' 0 0'<1   |&wv ' 0 0'<1   |&wv ''<1   |&wv ''<1   |&wv ''<1   |&ww// ''<1  _V? V? V?  V V V Vr       #"[ [ [ [ [6M M M M   ) ) ) )\ #"!	0 0 0 0 0B #"	: : : : : :B #"!L L L L L Lb #"!	    &        r0   