+
    iHàjéA  ã                  óà   € R t ^ RIHt ^ RIt^ RIHt ^ RIHt ^ RIH	t	H
t
Ht ^ RIHt ^ RIHtHt ^ RIHtHtHt ]P*                  ! R	4      tR
 R lt] ! R R4      4       tR tR tR R ltR# )aK  Per-response usage accounting for the conversation turn loop.

After every successful model API call, ``record_response_usage`` folds ``response.usage``
into: the context compressor (``update_from_response`` + the compression-budget rearm
latch), the usage anchor for display/compression math, per-session token/cost counters,
the state.db token-delta queue, and the observability log line. MoA sessions additionally
fold advisor fan-out usage into the reported counts and price the aggregator at its REAL
model/provider. Logger name stays ``agent.conversation_loop`` for caplog parity.
)ÚannotationsN)Úsuppress)Ú	dataclass)ÚAnyÚDictÚList)Úcalibrate_from_usage)Úcapture_usage_anchorÚset_usage_anchor)Úestimate_usage_costÚnormalize_usageÚwith_served_service_tierzagent.conversation_loopc               ó    € V ^8„  d   QhRRRR/# )é   Úagentr   ÚreturnÚstr© )Úformats   "Ú5/home/ubuntu/.hermes/hermes-agent/agent/turn_usage.pyÚ__annotate__r      s   € ÷ @ñ @ ð @¨ñ @ó    c                ó4   € ^ RI Hp V! \        V RR4      4      # )z¥The surface the agent's own row create would stamp (``_ensure_db_session``), so an
accounting guard that wins the row-creation race never mints an anonymous session.)Úsession_source_forÚplatformN)Úagent.session_sourcer   Úgetattr)r   r   s   & r   Ú_agent_session_sourcer      s   € õ 8Ùœg e¨Z¸Ó>Ó?Ð?r   c                  ó4   € ] tR t^ t$ RtR]R&   RtR]R&   RtR# )	ÚResponseUsageOutcomezŽ``compression_attempts`` is the (possibly rearmed-to-zero) budget counter;
``rearmed`` tells the loop to also clear its preflight-block latch.ÚintÚcompression_attemptsFÚboolÚrearmedr   N)Ú__name__Ú
__module__Ú__qualname__Ú__firstlineno__Ú__doc__Ú__annotations__r#   Ú__static_attributes__r   r   r   r   r       s   ‡ ñKð ÓØ€GˆT×r   r   c                 ó   € ^ RI Hp  V # )zALazy ``agent.conversation_loop`` import (avoids an import cycle).N)Úagent.conversation_loopÚconversation_loop)Ú_cls    r   Ú	_loop_modr/   )   s
   € å)à€Jr   c                óô  € Rp\        V RR4      pVe2   \        VR4      '       d     VP                  4       w  rBVe	   W,           pVeR   \        VR4      '       d@    \        V RR4      ;'       g    RpTP                  V P                  T;'       g    RR7       W1V3#   \         d!   p\        P                  RT4        Rp?LRp?ii ; i  \         d!   p\        P                  R	T4        Rp?LXRp?ii ; i)
zöMoA: fold advisor fan-out usage into REPORTED token counts (only aggregator usage is
returned, so advisor spend would be invisible) and flush the full-turn trace when
``moa.save_traces`` is on. Returns ``(client, canonical_usage, advisor_cost)``.NÚclientÚconsume_reference_usagez)MoA reference usage accounting failed: %sÚconsume_and_save_traceÚ _current_streamed_assistant_textÚ )Úaggregator_output_fallbackzMoA trace flush failed: %s)r   Úhasattrr2   Ú	ExceptionÚloggerÚdebugr3   Ú
session_id)r   Úcanonical_usageÚ_moa_ref_costÚ_moa_clientÚ
_ref_usageÚ_moa_acct_excÚ_agg_streamed_textÚ_moa_trace_excs   &&      r   Ú_fold_moa_usagerC   0   s  € ð €MÜ˜% ¨4Ó0€KØÒ¤7¨;Ð8Q×#RÒ#Rð	UØ(3×(KÑ(KÓ(MÑ%ˆJØÒ%Ø"1Õ">�ð Ò¤7¨;Ð8P×#QÒ#Qð	Gä!(¨Ð0RÐTVÓ!W×!]Ð!]Ð[]ÐØ×.Ñ.Ø× Ñ Ð=O×=WÐ=WÐSWð /ô ð
 ¨Ð6Ð6øô ô 	UÜ�L‰LÐDÀm×TÑTûð	Uûô ô 	GÜ�L‰LÐ5°~×FÑFûð	Gús;   §B ÁC Á0!C ÂC ÂC	Â)CÃC	ÃC7ÃC2Ã2C7c               ó8   € V ^8„  d   QhRRRRRRRRRR	R
RRRRR/# )r   r   r   ÚresponseÚmessageszlist[dict[str, Any]]Úapi_call_countr    Úapi_durationÚfloatr!   Úmax_compression_attemptsr   r   r   )r   s   "r   r   r   I   sb   € ÷ g\ñ g\Øðg\Øðg\Ø,@ðg\ØRUðg\àðg\à/2ðg\àNQðg\ð ñg\r   c               óÂ  € RpV P                   pV ;P                  ^,          un        \        VR4      '       d   VP                  '       g—   \	        VRR4      '       d   VP                  / 4       \	        VRR4      p	\        V	4      '       d   V	! 4        \        P                  RV P                  V P                  V P                  ;'       g    RV4       \        WWR7      # \        \        VP                  V P                  V P                  R	7      V4      p
T
p\        W
4      w  rÊpV
P                   pV
P"                  pV
P$                  p\	        VP                  R
R4      p\'        V\(        4      '       d
   V^ 8”  d   TMRpV'       d   \	        VP                  R^ 4      MRp\'        V\(        4      '       d   TMRpRT;'       g    TRTRV'       d
   VV,           MTRVe
   VV,
          MV
P*                  RV
P"                  RVf   V
P,                  MTRV
P.                  RV
P0                  /p\3        \	        VRR4      4      pVP                  V4       \5        YT;'       g    VP                   4       \7        T;'       g    VP                   VP"                  V4      pVe   \9        V VV^8H  R7       \)        \	        VR^ 4      ;'       g    ^ 4      p\;        4       P=                  VVVR,          VR7      '       d)   \        P                  RVR,          R VR VV4       ^ pRp\?        V4      V n         \)        T;'       g    VP                   ;'       g    ^ 4      V n!        \	        VRR4      '       d‹   VPD                  p\	        VRR4      '       d^   ^ RI#H$p V! V P                  V PJ                  VV P                  4       V PM                  V PN                   RVR RV P                   24       RVn(        RVn)        V ;PT                  V,          un*        V ;PV                  V,          un+        V ;PX                  V,          un,        V ;PZ                  V
P*                  ,          un-        V ;P\                  V
P"                  ,          un.        V ;P^                  V
P,                  ,          un/        V ;P`                  V
P.                  ,          un0        V ;Pb                  V
P0                  ,          un1        \e        \f        4      ;_uu_ 4        \	        V R R4      pVe   VPi                  \k        V4      4       \	        V R!R4      pVe/   TPi                  \)        V
P"                  ;'       g    ^ 4      4       RRR4       R"pV
P,                  '       d8   V'       d0   R#V
P,                   R$V R%^dV
P,                  ,          V,          R& R'2pV
P.                  '       d   VR(V
P.                   2,          p\	        VR)R4      p\'        V\l        4      '       d   V'       d   R*V 2MR"p\	        VR+R4      p \'        V \l        4      '       d   V '       d   VR,V  2,          p\        P                  R-V P                  V P                  V P                  ;'       g    RWïVVVV4
       V P                  ^8X  dU   V P                  ;'       g    R"R.8X  d:   \e        \f        4      ;_uu_ 4        ^ R/I7H8p! V!! WV P                  4       RRR4       V P                  V P                  V PJ                  p$p#p"Ve   \	        VR0R4      MRp%V%'       dk   V%Ps                  R14      '       dT   V%R1,          p"V%Ps                  R+4      ;'       g    V P                  p#V%Ps                  R24      ;'       g    V PJ                  p$\u        V"VV#V$\	        V R3R"4      R47      p&Rp'V&Pv                  e/   \k        V&Pv                  4      p'V ;Px                  V',          un<        Ve=    \k        V4      p(V(e-   V ;Px                  V(,          un<        T';'       g    R5V(,           p'V&P~                  V n@        V&P‚                  V nB        V P†                  '       Ed    V Pˆ                  '       dî    V PŠ                  '       g   V P�                  4        V P†                  P�                  V Pˆ                  \‘        V 4      V
P*                  V
P"                  V
P,                  V
P.                  V
P0                  T'V&P~                  V&P‚                  V P                  V PJ                  V&P~                  R68X  d   R7MRV P                  ^\	        V R8R"4      ;'       g    R"R97       V P”                  '       d8   \–        P’                  ! R;VR,          R R<VR,          R R=VR,          R 24       V
P,                  p*V
P.                  p+VR,          p,V*'       g	   V+'       dZ   V P˜                  '       gH   V,^ 8”  d   V*V,,          ^d,          M^ p-V P›                  V PN                   R>V*R R$V,R R?V-R& R@V+R RA2
4       \        WWR7      #   + '       g   i     ELì; i  + '       g   i     ELz; i  \z        \|        3 d    Rp( EL�i ; i  \f         d.   p)\        P“                  R:T Pˆ                  TT)4        Rp)?)ELTRp)?)ii ; i)BzÞFold ``response.usage`` into compressor, anchors, session counters, state.db
and the API-call log line (see module docstring). No-usage responses only
consume a pending compaction verdict. Returns the loop-visible outcome.FÚusageÚ%awaiting_real_usage_after_compressionÚnote_usage_less_responseNzUAPI call #%d: model=%s provider=%s in=? out=? total=? latency=%.1fs usage=unavailableÚunknown)r!   r#   )ÚproviderÚapi_modeÚinitial_prompt_tokensÚinitial_cached_tokensÚprompt_tokensÚcompletion_tokensÚtotal_tokensÚinput_tokensÚoutput_tokensÚcache_read_tokensÚcache_write_tokensÚreasoning_tokensÚ$_verify_compaction_cleared_threshold)Ú	turn_baseÚthreshold_tokens)Úcompleted_compaction_pendingrT   r^   zlCompression budget rearmed after provider-confirmed recovery: prompt=%s < threshold=%s (attempts were %s/%s)Ú,TÚ_context_probedÚ_context_probe_persistable)Úsave_provider_context_lengthu   ðŸ’¾ Cached context length: z tokens for Ú_api_latency_historyÚ_api_output_historyr5   z cache=Ú/z (z.0fz%)z write=Úidz id=rP   z
 upstream=zJAPI call #%d: model=%s provider=%s in=%d out=%d total=%d latency=%.1fs%s%sÚnous)Ú&maybe_switch_wire_after_first_responseÚlast_aggregator_slotÚmodelÚbase_urlÚapi_key)rP   rl   rm   g        ÚincludedÚsubscription_includedÚ_turn_route_task)ÚsourcerW   rX   rY   rZ   r[   Úestimated_cost_usdÚcost_statusÚcost_sourceÚbilling_providerÚbilling_base_urlÚbilling_moderk   rG   Útaskz4Token persistence failed (session=%s, tokens=%d): %szToken usage: prompt=z, completion=z, total=u      ðŸ’¾ Cache: z	 tokens (z% hit, z	 written))NÚcontext_compressorÚsession_api_callsr7   rL   r   Úupdate_from_responseÚcallabler9   Úinfork   rP   r   r   r   rQ   rC   rT   rX   rV   Ú
isinstancer    rW   rY   rZ   r[   r"   r   r	   r
   r/   Ú _should_rearm_compression_budgetÚdictÚ_last_turn_usageÚ_last_prompt_size_tokensÚcontext_lengthÚagent.model_metadatarc   rl   Ú_safe_printÚ
log_prefixra   rb   Úsession_prompt_tokensÚsession_completion_tokensÚsession_total_tokensÚsession_input_tokensÚsession_output_tokensÚsession_cache_read_tokensÚsession_cache_write_tokensÚsession_reasoning_tokensr   r8   ÚappendrI   r   Úagent.nous_wireri   Úgetr   Ú
amount_usdÚsession_estimated_cost_usdÚ	TypeErrorÚ
ValueErrorÚstatusÚsession_cost_statusrq   Úsession_cost_sourceÚ_session_dbr;   Ú_session_db_createdÚ_ensure_db_sessionÚqueue_token_countsr   r:   Úverbose_loggingÚloggingÚ
quiet_modeÚ_vprint).r   rE   rF   rG   rH   r!   rJ   r#   Ú
compressorÚ_note_usage_lessr<   Úaggregator_usager>   r=   rT   rU   rV   Ú_initial_promptÚcontext_prompt_tokensÚ_initial_cachedÚcontext_cache_readÚ
usage_dictÚ_completed_compaction_pendingÚ_new_anchorÚ_compression_thresholdÚctxrc   ÚhistÚohistÚ
_cache_pctÚ_ridÚ_identÚ	_upstreamri   Ú_agg_cost_modelÚ_agg_cost_providerÚ_agg_cost_base_urlÚ	_agg_slotÚcost_resultÚ_cost_deltaÚ	_moa_costÚeÚcachedÚwrittenÚpromptÚhit_pcts.   &&$$$$$                                       r   Úrecord_response_usager¿   I   sÏ	  € ð €GØ×)Ñ)€Jð 
×Ò˜qÕ ÕÜ�H˜g×&Ò&¨8¯>¯>¨>Ü�:ÐFÈ×NÒNð ×+Ñ+¨BÔ/Ü" :Ð/IÈ4ÓPÐÜÐ$×%Ò%ÙÔÜ�‰ØcØ×#Ñ# U§[¡[°%·.±.×2MÐ2MÀIÈ|ô	
ô $Ð9MÔ_Ð_ä.Ü˜Ÿ™°·±È%Ï.É.ÔYÐ[cóe€Oð 'ÐÜ2AÀ%Ó2YÑ/€K -Ø#×1Ñ1€MØ'×5Ñ5ÐØ"×/Ñ/€Lô ˜hŸn™nÐ.EÀtÓL€OÜ/9¸/Ì3×/OÒ/OÐTcÐfgÔTg™OÐmqÐçMb”g˜hŸn™nÐ.EÀqÔIÐhl€OÜ,6°Ì×,LÒ,L™ÐRVÐð 	Ð.×?Ð?°-ØÐ.Ø×G\Ð.Ð1BÖBÐbnØÐHZÒHfÐ.Ð1CÖCÐl{÷  mIñ  mIØ˜×6Ñ6ØÐBTÒB\˜_×>Ò>ÐbtØ˜o×@Ñ@Ø˜O×<Ñ<ð	€Jô %)Ü�
ÐBÀEÓJó%Ð!ð ×#Ñ# JÔ/ô ˜Ð*?×*aÐ*aÐCS×CaÑCaÔbÜ&Ø×?Ð?Ð!1×!?Ñ!?ÐAQ×A_ÑA_Ðaió€Kð ÒÜ˜ °~ÈÑ7JÕKÜ ¤¨Ð5GÈÓ!K×!PÐ!PÈqÓQÐÜƒ{×3Ñ3ØÐ;XØ  Õ1ÐDZð 4÷ ò ô 	�‰ðGà˜/Õ*¨1Ð-Ø% aÐ(Ø Ø$ô	
ð  !Ðð ˆô " *Ó-€EÔô &)Ð)>×)eÐ)eÐBR×B`ÑB`×)eÐ)eÐdeÓ%f€EÔ"ô ˆzÐ,¨e×4Ò4Ø×'Ñ'ˆÜ�:Ð;¸U×CÒCÝIá(¨¯©°e·n±nÀcÈ5Ï>É>ÔZØ×Ñ ×!1Ñ!1Ð 2Ð2NÈsÐSTÈgÐUaÐbg×bmÑbmÐanÐoÔpØ%*ˆ
Ô"Ø05ˆ
Ô-à	×Ò =Õ0ÕØ	×#Ò#Ð'8Õ8Õ#Ø	×Ò ,Õ.ÕØ	×Ò /×">Ñ">Õ>ÕØ	×Ò ?×#@Ñ#@Õ@ÕØ	×#Ò# ×'HÑ'HÕHÕ#Ø	×$Ò$¨×(JÑ(JÕJÕ$Ø	×"Ò" o×&FÑ&FÕFÕ"ä	”)×	Õ	Ü�uÐ4°dÓ;ˆØÒØ�K‰Kœ˜lÓ+Ô,Ü˜Ð4°dÓ;ˆØÒØ�L‰Lœ˜_×:Ñ:×?Ð?¸aÓ@ÔA÷ 
ð €JØ×(×(Ð(¯]Ø˜×@Ñ@ÐAÀÀ=À/ÐQSÐTWÐXg×XyÑXyÕTyð  {Hõ  UHð  ILð  TMð  MOð  Pˆ
ð
 ×)×)Ð)Ø˜ × BÑ BÐCÐDÕDˆ
Ü�8˜T 4Ó(€DÜ(¨¬s×3Ò3¿ˆt�D�6‰]À"€FÜ˜ *¨dÓ3€IÜ�)œS×!Ò!§iØ�J˜y˜kÐ*Õ*ˆÜ
‡K�KØTØ×Ñ §¡¨e¯n©n×.IÐ.IÀ	Ø¨,Ø�j &ô	ð ×Ñ !Ô#¨¯©×)=Ð)=¸2À&Ô(HÜ”i× Õ ÝNÙ2°5ÀE×D[ÑD[Ô\÷ !ð ?D¿k¹kÈ5Ï>É>Ð[`×[iÑ[iÐ);Ð'€OØFQÒF]”˜Ð%;¸TÔBÐcg€Iß�Y—]‘] 7×+Ò+Ø# GÕ,ˆØ&Ÿ]™]¨:Ó6×HÐH¸%¿.¹.ÐØ&Ÿ]™]¨:Ó6×HÐH¸%¿.¹.ÐÜ%ØÐ)Ð4FØ#¬W°U¸IÀrÓ-Jô€Kð €KØ×ÑÒ)Ü˜K×2Ñ2Ó3ˆØ×(Ò(¨KÕ7Õ(ØÒ ð	Ü˜mÓ,ˆIð Ò Ø×,Ò,°	Õ9Õ,Ø&×-Ð-¨#°Õ:ˆKØ +× 2Ñ 2€EÔØ +× 2Ñ 2€EÔð ××Ñ˜U×-×-Ð-ð	ð ×,×,Ð,Ø×(Ñ(Ô*Ø×Ñ×0Ñ0Ø× Ñ Ü,¨UÓ3Ø,×9Ñ9Ø-×;Ñ;Ø"1×"CÑ"CØ#2×#EÑ#EØ!0×!AÑ!AØ#.Ø'×.Ñ.Ø'×.Ñ.Ø!&§¡Ø!&§¡à×%Ñ%¨Ô3ñ 5Ø9=Ø—k‘kØ Ü˜UÐ$6¸Ó;×AÐA¸rð# 1ô ð2 ××ÐÜ�ŠÐ,¨Z¸Õ-HÈÐ,KÈ=ÐYcÐdwÕYxÐyzÐX{ð  |Dð  EOð  P^õ  E_ð  `að  Dbð  cô  	dð ×.Ñ.€FØ×0Ñ0€GØ˜Õ(€Fß—' 5×#3×#3Ð#3Ø-3°a¬Z�6˜F•? SÖ(¸QˆØ�‰Ø×ÑÐ  Ø�aˆj˜˜& ˜ð $Ø˜ˆ}˜G G¨A ;¨ið9ô	
ô
  Ð5IÔ[Ð[÷e 
×	Ð	ú÷< !× Ð ûô4 œ:Ð&ô 	Ø‹Ið	ûôJ ô 	Ü�L‰LØFØ× Ñ  ,°÷ò ûð	úsV   ÔAi$Õ6i$Û-i8àj âj& â+Cj& å=j& é$i5	é8j		êj#ê"j#ê&kê1"këk)r(   Ú
__future__r   rž   Ú
contextlibr   Údataclassesr   Útypingr   r   r   Úagent.image_token_costr   Úagent.usage_anchorr	   r
   Úagent.usage_pricingr   r   r   Ú	getLoggerr9   r   r   r/   rC   r¿   r   r   r   Ú<module>rÈ      sk   ðñõ #ã Ý Ý !ß "Ñ "å 7ß Eß ^Ñ ^à	×	Ò	Ð4Ó	5€õ@ð ÷ð ó ðòò7÷2g\r   