
    i~                    $   U d dl m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 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           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)           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           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d0           ed1          dd d!"          d2 e ed(           ed3           ed4           ed5          dd d!"          d6 e ed'           ed(           ed)           ed*          dd d!"          d7 e ed8           ed9           ed1          dd:d;<          d= e ed>           ed?           ed@          dd:d;<          dA e edB           edC           ed          dd:d;<          dD e edE           edF           ed0          dd:d;<          dG e ed0           edE           edH          dd:d;<          dI e ed9           edJ           ed8          dd:d;<          i dK e edL           edM           edN          dd:d;<          dO e ed'           ed(           ed)           ed*          dd d!"          dP e edQ           edR           edS           ed/          dd d!"          dT e ed(           ed3           ed4           ed5          dd d!"          dU e edV           ed1           edW           ed)          dd d!"          dX e edY           edZ          dd[d\]          d^ e edN           ed_          dd[d\]          d` e ed1           ed9          ddadb]          dc e ed>           ed?          ddadb]          dd e ed0           edE          ddadb]          de e ed(           ed3          ddfdg]          dh e ed'           ed(          ddfdg]          di e ed'           ed(          ddfdg]          dj e edQ           edR          ddfdg]          dk e edQ           edl          ddfdg]          dm e edn           edo          ddfdg]          dp e edq           edY          ddfdg]           e ed)           edr          ddst           e ed)           edr          ddst          duZdvedw<   dd|Zdd~Z 	 	 dddZ!ddZ"ddZ#ddZ$ddZ%	 	 	 dddZ&dddddZ'ddddddZ(	 	 	 dddZ)ddZ*ddZ+dS )    )annotationsN)	dataclass)datetimetimezone)Decimal)AnyDictLiteralOptional)fetch_endpoint_model_metadatafetch_model_metadata)base_url_host_matchesg        )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    8/home/piyush/.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,   )r0   r#   r-   s    r/   total_tokenszCanonicalUsage.total_tokens+   s    !D$666r1   )r*   r!   )__name__
__module____qualname__r"   __annotations__r#   r$   r%   r&   r(   r)   propertyr0   r3    r1   r/   r    r       s         LMM*.I....T T T XT 7 7 7 X7 7 7r1   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)r4   r5   r6   r7   r@   rA   r9   r1   r/   r;   r;   0   sF         MMMJJJH!L!!!!!!r1   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)r4   r5   r6   rE   r7   rF   rG   rH   rI   rK   rM   rN   rP   r9   r1   r/   rC   rC   8   s         0444441555555999996: ::::&*L****F $J$$$$%)O))))%)J))))))r1   rC   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 )
CostResultrD   
amount_usd
CostStatusstatusrJ   rK   r<   labelNrO   rP   rL   rN   r9   ztuple[str, ...]notes)r4   r5   r6   r7   rP   rN   rW   r9   r1   r/   rR   rR   E   sr         !!!!JJJ%)J))))%)O))))Er1   rR   c                 >    t          j        t          j                  S r,   )r   nowr   utcr9   r1   r/   <lambda>r[   P   s    8<-- r1   )	anthropiczclaude-opus-4-7z5.00z25.00z0.50z6.25r   z8https://platform.claude.com/docs/en/about-claude/pricingzanthropic-pricing-2026-05)rE   rF   rG   rH   rK   rM   rN   )r\   zclaude-opus-4-7-20250507)r\   zclaude-opus-4-6)r\   zclaude-opus-4-6-20250414)r\   zclaude-sonnet-4-6z3.00z15.00z0.30z3.75)r\   zclaude-sonnet-4-6-20250414)r\   zclaude-opus-4-5)r\   zclaude-sonnet-4-5)r\   zclaude-haiku-4-5z1.00z0.10z1.25)r\   zclaude-opus-4-20250514z75.00z1.50z18.75)r\   zclaude-sonnet-4-20250514)openaizgpt-4oz2.50z10.00zhttps://openai.com/api/pricing/zopenai-pricing-2026-03-16)rE   rF   rG   rK   rM   rN   )r]   zgpt-4o-miniz0.15z0.60z0.075)r]   zgpt-4.1z2.00z8.00)r]   zgpt-4.1-miniz0.40z1.60)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-20241022)r\   zclaude-3-5-haiku-20241022z0.80z4.00z0.08)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)rE   rF   rK   rM   rN   )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-flash)r`   zgemini-2.0-flash)bedrockzanthropic.claude-opus-4-6z'https://aws.amazon.com/bedrock/pricing/zbedrock-pricing-2026-04)ra   zanthropic.claude-sonnet-4-6)ra   zanthropic.claude-sonnet-4-5)ra   zanthropic.claude-haiku-4-5)ra   zamazon.nova-proz3.20)ra   zamazon.nova-litez0.06z0.24)ra   zamazon.nova-microz0.035z1.20zminimax-pricing-2026-04)rE   rF   rK   rN   ))minimaxminimax-m2.7)
minimax-cnrc   z#Dict[tuple[str, str], PricingEntry]_OFFICIAL_DOCS_PRICINGvaluer   r*   rD   c                f    | d S 	 t          t          |                     S # t          $ r Y d S w xY wr,   )r   r<   	Exceptionrf   s    r/   _to_decimalrj     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!   rh   ri   s    r/   _to_intrl     s9    5:A   qqs    
!!
model_namer<   r=   rL   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t	          |pdd	          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 r.t          ||                    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@   rA   
openrouterzopenrouter.aiofficial_models_apir\   r   r]   >   rb   rd   >   localcustom	localhostru   r   )striplowersplitr;   r   )rm   r=   r@   provider_namebaser>   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{||||##[C8H8H8LW_Wece  uM  N  N  N  	N  XU[[5E5Eb5IT\Tb`b  rJ  K  K  K  	K111]%++c:J:J2:NYaYgeg  wO  P  P  P  	P++++9L9L]%>heV^Vdbds|}}}}!;)[`Ch5;;sCSCSTVCWCWfhs{  tB  @B  QZ  [  [  [  [r1   r>   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/Nz(\d+)\.(\d+)z\1-\2)rx   rw   
startswithlenresub)r>   names     r/   _normalize_anthropic_model_namer   !  sc     ;;==  D|$$ (C%%&&' 6/8T22DKr1   routeOptional[PricingEntry]c                   | j                                         }t                              | j        |f          }|r|S | j        dk    r:t          |          }||k    r%t                              | j        |f          }|r|S d S )Nr\   )r>   rx   re   getr=   r   )r   r>   entry
normalizeds       r/   _lookup_official_docs_pricingr   2  s    KE"&&'>??E ~$$4U;;
*..
/KLLE 4r1   c                J    t          t                      | j        dd          S )Nz>https://openrouter.ai/docs/api/api-reference/models/get-modelszopenrouter-models-apirM   rN   )_pricing_entry_from_metadatar   r>   )r   s    r/   _openrouter_pricing_entryr   B  s-    'S/	   r1   metadataDict[str, Dict[str, Any]]model_idrM   rN   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_writerf   rD   r*   c                    | d S | t           z  S r,   )_ONE_MILLIONri   s    r/   _per_token_to_per_millionz?_pricing_entry_from_metadata.<locals>._per_token_to_per_millione  s    =4|##r1   r   )	rE   rF   rG   rH   rI   rK   rM   rN   rP   )rf   rD   r*   rD   )r   rj   rC   _UTC_NOW)r   r   rM   rN   r   r   r   r   r   r   r   s              r/   r   r   K  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$'::
 
 
 
r1   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@   rp   r   included-route)rE   rF   rG   rH   rK   rN   rq   r?   )r   ro   z/modelszopenai-compatible-models-apir   )r~   rA   rC   _ZEROr=   r   r@   r   r   r>   rstripr   rm   r=   r@   r   r   r   s         r/   get_pricing_entryr   w  s     "*x(SSSE444#($)(-).,
 
 
 	
 ~%%(///~ ,)%.'-RPPPK.//44===:	
 
 
  	L(///r1   )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                    }n|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          }|st          t	          | dd                    }t          |
rt	          |
dd          nd          }|st          t	          | d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_tokensr0   completion_tokensprompt_tokens_detailsr%   output_tokens_detailsr&   )r"   r#   r$   r%   r&   )r    rw   rx   rl   getattrmax)r   r=   r   rz   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[[  	_ '@Y[\(](] ^ ^$9@GGG11555a
 
 " 	!((EqII" " 1l->>ASSTT^-DdKKN S"7>;Mq#Q#QRR!#+-)   r1   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   rp   r   r   r   )rS   rU   rK   rV   rN   r   r   zn/a)rS   rU   rK   rV   )z(cache-read pricing unavailable for route)rS   rU   rK   rV   rW   )z)cache-write pricing unavailable for router   z~$.2frq   zBOpenRouter cost is estimated from the models API until reconciled.)rS   rU   rK   rV   rP   rN   rW   )r~   rA   rR   r   r   r"   rE   rK   r#   rF   r$   rG   r%   rH   r   r   rI   r(   r=   appendrP   rN   tuple)rm   r   r=   r@   r   r   r   rW   amountrU   rV   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   r1   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   rp   Tr   N)r~   rA   r   r   s         r/   has_known_pricingr   -  sN     "*x(SSSE444tj8hX_```Er1   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>>>>r1   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   )rf   	abs_valuesignunits	thresholdsuffixscaledtexts           r/   format_token_count_compactr   N  s    CJJI53u::!))33DBE" + +	6	!!*F{{ #  d{{{{3''..s33*D*&***** " <<r1   )rf   r   r*   rD   )rf   r   r*   r!   )NN)rm   r<   r=   rL   r@   rL   r*   r;   )r>   r<   r*   r<   )r   r;   r*   r   )
r   r   r   r<   rM   r<   rN   r<   r*   r   )NNN)
rm   r<   r=   rL   r@   rL   r   rL   r*   r   )r   r   r=   rL   r   rL   r*   r    )rm   r<   r   r    r=   rL   r@   rL   r   rL   r*   rR   )
rm   r<   r=   rL   r@   rL   r   rL   r*   r   )r   r   r*   r<   )rf   r!   r*   r<   ),
__future__r   r   dataclassesr   r   r   decimalr   typingr   r	   r
   r   agent.model_metadatar   r   utilsr   DEFAULT_PRICINGr   r   rT   rJ   r    r;   rC   rR   r   re   r7   rj   rl   r~   r   r   r   r   r   r   r   r   r   r   r9   r1   r/   <module>r      s   " " " " " " " 				 ! ! ! ! ! ! ' ' ' ' ' ' ' '       / / / / / / / / / / / / T T T T T T T T ' ' ' ' ' '3//wy!!AB

 $7 7 7 7 7 7 7 7$ $" " " " " " " " $	* 	* 	* 	* 	* 	* 	* 	* $                .-
\?
 |&wv ' 0 0$+GFOO%,WV__'M3  \?" |&wv ' 0 0$+GFOO%,WV__'M3  )\?< |&wv ' 0 0$+GFOO%,WV__'M3  C\?T |&wv ' 0 0$+GFOO%,WV__'M3  [\?l |&wv ' 0 0$+GFOO%,WV__'M3  s\?D |&wv ' 0 0$+GFOO%,WV__'M3  K\?^ |&wv ' 0 0$+GFOO%,WV__'M3  e\?v |&wv ' 0 0$+GFOO%,WV__'M3  }\?N |&wv '$+GFOO%,WV__'M3  U\?h |&ww// ' 0 0$+GFOO%,WW%5%5'M3  o\?@ |&wv ' 0 0$+GFOO%,WV__'M3  G\?Z |&wv ' 0 0$+GFOO'43  a\?p |&wv '$+GG$4$4'43  w\?F |&wv '$+GFOO'43  M\?\ |&wv '$+GFOO'43  c\?r |&wv '$+GG$4$4'43  y\?H |&ww// ' 0 0$+GFOO'43  O\? \?^ |&wv '$+GFOO'43  e\?v |&wv ' 0 0$+GFOO%,WV__'M3  }\?N |&wv '$+GFOO%,WV__'M3  U\?f |&ww// ' 0 0$+GFOO%,WW%5%5'M3  m\?~ |&wv '$+GFOO%,WV__'M3  E\?X |&wv ''F5  _\?l |&wv ''F5  s\?B	 |&wv ' 0 0'23  I	\?V	 |&wv ''23  ]	\?j	 |&wv ''23  q	\?F
 |&ww// ' 0 0'<1  M
\?Z
 |&wv ' 0 0'<1  a
\?n
 |&wv ' 0 0'<1  u
\?B |&wv ''<1  I\?V |&wv ''<1  ]\?j |&wv ''<1  q\?~ |&ww// ''<1  E\? \?Z |&wv ''1	   |&wv ''1	  m\? \? \?  \ \ \ \~       #"[ [ [ [ [:   "       ) ) ) )\ #"!	0 0 0 0 0B #"	F F F F F FZ #"!L L L L L Lb #"!	    &        r1   