+
    „WÝj(  ã                  óT  € R t ^ RIHt ^ RIt^ RIt^ RIHt ^ RIHtH	t	 ^RI
Ht ^RI
Ht ]P                  ! ]4      tR#tR$t]! RR04      t]! 0 R%m4      tR	 R
 ltR R ltR R ltR R lt] ! R R4      4       tR R ltR R ltR R ltR R ltRRRRRRRRRRR ^/R! R" llt R# )&a  Per-model quality, friction and context-pressure shared metrics.

Tool-call quality is counted where the agent validates the calls a model emitted (every call,
clean ones as ``issue=none``, so rates have a denominator). Friction and context peaks are
attributed to the model that produced the turn, which the relay runtime tracks per metrics session
in :class:`ModelSessionState`. Provider/model always go through ``model_call_fields`` (the catalog
helpers), so custom endpoints and loopback servers read ``custom``.
)ÚannotationsN)Ú	dataclass)ÚAnyÚIterable)Úshared_metrics_contract)Úshared_metrics_fieldsÚcontext_overflowÚpayload_too_largec               ó$   € V ^8„  d   QhRRRRRR/# )é   Úproviderr   ÚmodelÚreturnúdict[str, str]© )Úformats   "ÚaC:\Users\johnn\AppData\Local\hermes\hermes-agent\hermes_cli\observability\shared_metrics_model.pyÚ__annotate__r   "   s&   € ÷ Nñ N˜#ð N cð N¨nñ Nó    c                ó6   € \         P                  ! R V RV/4      # ©r   r   )ÚcontractÚmodel_call_fieldsr   s   &&r   Úmodel_router   "   s   € Ü×%Ò% z°8¸WÀeÐ&LÓMÐMr   c               ó    € V ^8„  d   QhRRRR/# )r   Úcontext_lengthr   r   Ústrr   )r   s   "r   r   r   &   s   € ÷ [ñ [ #ð [¨#ñ [r   c                óz   € \         P                  ! V 4      pV'       d   \         P                  ! V\        R 4      # R# )Úgte_1mÚunknown)r   Ú_non_negative_numberÚ_bucketÚ_WINDOW_THRESHOLDS)r   Úlengths   & r   Úwindow_bucketr$   &   s0   € Ü×*Ò*¨>Ó:€FßEKŒ8×Ò˜FÔ$6¸ÓAÐZÐQZÐZr   c               ó$   € V ^8„  d   QhRRRRRR/# )r   Úsignalr   Úrouteúdict[str, str] | Noner   r   )r   s   "r   r   r   +   s(   € ÷ Dñ D˜Cð DÐ(=ð DÐBWñ Dr   c                óh   € V \         P                  9  d   R # / T;'       g    \        R R 4      CRV /C# )Nr&   )r   ÚFRICTION_SIGNALSr   )r&   r'   s   &&r   Úfriction_fieldsr+   +   s4   € Ø”X×.Ñ.Ô.ÙØCˆu×/Ð/œ D¨$Ó/ÐC°(¸FÑCÐCr   c               ó    € V ^8„  d   QhRRRR/# )r   Úusager   r   úfloat | Noner   )r   s   "r   r   r   1   s   € ÷ fñ f˜#ð f ,ñ fr   c                óÒ   € \        V \        4      '       g   R # \        P                  ! V P	                  R4      4      pVe   V# \        P                  ! V P	                  R4      4      # )NÚprompt_tokensÚinput_tokens)Ú
isinstanceÚdictr   r    Úget)r-   Útokenss   & r   Ú_prompt_tokensr6   1   sP   € Ü�eœT×"Ò"ÙÜ×*Ò*¨5¯9©9°_Ó+EÓF€FØÒ'ˆ6Ðe¬X×-JÒ-JÈ5Ï9É9ÐUcÓKdÓ-eÐer   c                  óº   € ] tR t^8t$ RtRtR]R&   RtR]R&   RtR]R&   Rt	R]R	&   R
t
R]R&   ^ tR]R&   RtR]R&   R R ltR R ltR R ltR R ltR R ltRtR# )ÚModelSessionStatezZPer-session model attribution the runtime keeps between hooks (caller holds session.lock).Nr(   Ú
last_routeÚ
peak_routeÚfloatÚpeak_tokensr.   Úpeak_windowFÚboolÚ	limit_hitÚintÚfailed_turn_nsÚfailed_routec               ó(   € V ^8„  d   QhRRRRRRRR/# )r   r'   r   r-   r   r   r   ÚNoner   )r   s   "r   r   ÚModelSessionState.__annotate__D   s/   € ÷ 	Xñ 	X .ð 	X¸ð 	XÈcð 	XÐVZñ 	Xr   c                ó0  € Wn         \        V4      \        P                  ! V4      rTV P                  f   Wn        Ve	   V'       g   R# V P
                  e)   WE,          V P                  V P
                  ,          8”  d   WVuV n        V n        V n        R# R# )zKOne finished primary call: remember its model and the fullest context seen.N)r9   r6   r   r    r:   r=   r<   )Úselfr'   r-   r   r5   Úwindows   &&&&  r   Úobserve_callÚModelSessionState.observe_callD   sz   € àŒÜ'¨Ó.´×0MÒ0MÈnÓ0]�Ø�?‰?Ò"Ø#ŒOØŠ>§ÙØ×ÑÒ# v¥¸×9IÑ9IÈD×L\ÑL\Õ9\Ô'\ØBGÐQWÐ?ˆDŒO˜TÔ-¨tÖ/?ñ (]r   c               ó$   € V ^8„  d   QhRRRRRR/# )r   r'   r   Úerror_classr   r   rD   r   )r   s   "r   r   rE   O   s!   € ÷ "ñ " >ð "Àð "Èñ "r   c                ób   € Wn         V P                  f   Wn        V\        9   d
   RV n        R# R# )z‡A failed primary call still names the model: a session whose every call overflowed
is exactly the one the context peak row must report.NT)r9   r:   Ú_LIMIT_ERROR_CLASSESr?   )rG   r'   rL   s   &&&r   Úobserve_errorÚModelSessionState.observe_errorO   s-   € ð  ŒØ�?‰?Ò"Ø#ŒOØÔ.Ô.Ø!ˆDŽNñ /r   c               ó(   € V ^8„  d   QhRRRRRRRR/# )	r   Úoutcomer   r'   r(   Únow_nsr@   r   rD   r   )r   s   "r   r   rE   X   s0   € ÷ Kñ K Cð KÐ0Eð KÈsð KÐW[ñ Kr   c                óŠ   € VR8H  pV'       d   TM^ V n         V'       d   T;'       g    V P                  V n        R# RV n        R# )zJOnly the trailing turn matters for abandonment: a later success clears it.ÚfailedN)rA   r9   rB   )rG   rR   r'   rS   rU   s   &&&& r   Úobserve_turnÚModelSessionState.observe_turnX   s5   € à˜HÑ$ˆß(.™f°AˆÔß:@˜U×5Ð5 d§o¡oˆÖÀdˆÖr   c               ó    € V ^8„  d   QhRRRR/# )r   rS   r@   r   r(   r   )r   s   "r   r   rE   ^   s   € ÷ ñ ¨#ð Ð2Gñ r   c                	ó    € V P                   '       d<   WP                   ,
          \        8:  d!   V P                  ;'       g    V P                  # R # ©N)rA   ÚQUICK_ABANDON_NSrB   r9   )rG   rS   s   &&r   Úquick_abandon_routeÚ%ModelSessionState.quick_abandon_route^   s:   € Ø××Ð 6×,?Ñ,?Õ#?ÔCSÔ#SØ×$Ñ$×7Ð7¨¯©Ð7Ùr   c               ó   € V ^8„  d   QhRR/# )r   r   r(   r   )r   s   "r   r   rE   c   s   € ÷ 
ñ 
Ð%:ñ 
r   c           	     ó6  € V P                   f   R# V P                  RJp/ V P                   CRV P                  '       d   RMRRV'       d,   \        P                  ! V P
                  V P                  4      MRRV'       d   \        V P                  4      /C# R/C# )zMOne row per session that reached a primary model; None when no call was made.Nr?   ÚyesÚnoÚpeak_fill_bucketr   r$   )r:   r=   r?   Úfields_Úcontext_fill_bucketr<   r$   )rG   Úknowns   & r   Úcontext_peak_fieldsÚ%ModelSessionState.context_peak_fieldsc   s�   € à�?‰?Ò"ÙØ× Ñ ¨Ð,ˆð
Ø�o‰oð
à $§.§. .™°dØßSX”×+Ò+¨D×,<Ñ,<¸d×>NÑ>NÔOÐ^gàÇœ]¨4×+;Ñ+;Ó<ñ
ð 	
ð LUñ
ð 	
r   )rB   rA   r9   r?   r:   r<   r=   g      ð¿)Ú__name__Ú
__module__Ú__qualname__Ú__firstlineno__Ú__doc__r9   Ú__annotations__r:   r<   r=   r?   rA   rB   rI   rO   rV   r\   rf   Ú__static_attributes__r   r   r   r8   r8   8   sn   ‡ ádà(,€JÐ%Ó,Ø(,€JÐ%Ó,Ø€K�ÓØ $€K�Ó$Ø€IˆtÓØ€N�CÓØ*.€LÐ'Ó.õ	Xõ"õKõ÷

ñ 
r   r8   c               ó    € V ^8„  d   QhRRRR/# )r   Ústart_fieldsr(   r   r>   r   )r   s   "r   r   r   r   s   € ÷ `ñ `Ð0ð `°Tñ `r   c                óX   € \        V 4      ;'       d    V P                  R 4      \        9  # )Ú
entrypoint)r>   r4   Ú_UNATTENDED_ENTRYPOINTS)rp   s   &r   Úattendedrt   r   s&   € Ü�Ó×_Ð_ ,×"2Ñ"2°<Ó"@ÔH_Ñ"_Ð_r   c               ó    € V ^8„  d   QhRRRR/# )r   ÚtoolszIterable[Any] | Noner   údict[str, tuple[str, ...]]r   )r   s   "r   r   r   x   s   € ÷ 	ñ 	Ð0ð 	Ð5Oñ 	r   c                ó
  € / pT ;'       g    R Fð  p\        V\        4      '       d   VP                  R 4      MRp\        V\        4      '       d&   \        VP                  R4      \        4      '       g   Ki  VP                  R4      p\        V\        4      '       d   VP                  R4      MRp\        V\        4      '       d-   \
        ;QJ d    . R V 4       F  NK  	  5M! R V 4       4      MRWR,          &   Kò  	  V# )ÚfunctionNÚnameÚ
parametersÚrequiredc              3  óV   "  € T F  p\        V\        4      '       g   K  Vx € K!  	  R # 5irZ   )r2   r   )Ú.0Úns   & r   Ú	<genexpr>Ú#_required_params.<locals>.<genexpr>€   s   é € Ð$L±¨1¼ÀAÄs×9K§Q¢Q³ùs   ‚)Ÿ
)r   )r2   r3   r4   r   ÚlistÚtuple)rv   r|   ÚtoolÚfnÚparamsÚnamess   &     r   Ú_required_paramsrˆ   x   sÀ   € Ø+-€HØ—�˜’ˆÜ%/°´d×%;Ò%;ˆT�X‰X�jÔ!ÀˆÜ˜"œd×#Ò#¬:°b·f±f¸V³nÄc×+JÒ+JÙØ—‘˜Ó%ˆÜ*4°V¼T×*BÒ*B�—
‘
˜:Ô&ÈˆÜPZÐ[`Ôbf×PgÒPgŸuœuÑ$L±Ó$LŸu™uÑ$L±Ó$LÔLÐmoˆ�F•Óñ ð €Or   c               ó0   € V ^8„  d   QhRRRRRRRRRRR	R
/# )r   rz   r   Úraw_argsÚvalid_namesr|   rw   Úrepairedr>   r   r   r   )r   s   "r   r   r   „   s<   € ÷ .ñ .Ø
ð.Øð.Ø.1ð.Ø=Wð.Øcgð.àñ.r   c               ó   a€ W9  d   R# VP                  V R
4      p\        V\        \        34      '       d   VoMYVe    \	        V4      P                  4       '       g   V'       d   R# V'       d   R# R#  \        P                  ! \	        V4      4      o\        S\        4      '       dA   \        ;QJ d    V3R lV 4       F  '       g   K   RM	  RM! V3R lV 4       4      '       d   R	# V'       d   R# R#   \        \        3 d     R# i ; i)zûThe first problem with one emitted call, most severe first; ``none`` when clean.

Empty arguments are only an issue when the tool declares required parameters: for a
parameterless tool Hermes's normalization to ``{}`` is exactly what the model meant.
Úunknown_toolÚempty_argumentsrŒ   ÚnoneÚinvalid_jsonc              3  ó,   <"  € T F	  qS9  x € K  	  R # 5irZ   r   )r~   ÚkeyÚparseds   & €r   r€   Ú"tool_call_issue.<locals>.<genexpr>˜   s   øé € Ð*OÉÀ°fÖ+<Ëùs   ƒTFÚschema_mismatchr   )r4   r2   r3   r‚   r   ÚstripÚjsonÚloadsÚ	TypeErrorÚ
ValueErrorÚany)rz   rŠ   r‹   r|   rŒ   Úneededr”   s   &&$$$ @r   Útool_call_issuerž   „   sÐ   ø€ ð ÔÙØ�\‰\˜$ Ó#€FÜ�(œT¤4˜L×)Ò)Ø‰Ø	Ò	¤ X£×!4Ñ!4×!6Ò!6ß$*Ð ÐT¿x°ÐTÈVÐTð	"Ü—Z’Z¤ H£Ó.ˆFô �fœd×#Ò#§s£sÔ*OÉÓ*O§s§s¢sÔ*OÉÓ*O×'OÒ'OÙ ß!ˆ:Ð- vÐ-øô	 œ:Ð&ô 	"Ú!ð	"ús   Á5C8 Ã8DÄDc               ó(   € V ^8„  d   QhRRRRRRRR/# )	r   Úagentr   Ú
tool_callszIterable[Any]Úrepaired_idszfrozenset[int] | set[int]r   rD   r   )r   s   "r   r   r   �   s0   € ÷ Uñ U Cð U°]ð UÐRkð UÐptñ Ur   c                ó  €  ^RI HpHp V'       d   V! 4       '       g   R# ^RIHp ^RIHp \        \        V RR4      \        V RR4      4      p\        V RR4      ;'       g    \        4       p\        \        V RR4      4      p	\        V4      pV! Wq4      ;p
e   V! \        P                  V
4       V F¤  pVP                  p\        VP                   VP"                  Y‰\%        V4      V9   ;'       g    \        VR	R
4      RJ R7      pV! \        P&                  / VCRRRV/C4       V! WP                   W×4      ;pf   K�  V! \        P(                  V4       K¦  	  R#   \*         d    \,        P/                  RRR7        R# i ; i)a  Count every tool call one primary response emitted, before Hermes normalizes it.

``repaired_ids`` holds ``id(tc)`` of calls whose name Hermes auto-repaired; streamed calls
whose argument JSON was repaired carry ``function.args_repaired``. No-op unless enabled.
)ÚenabledÚrecord_process_markN)Útool_unavailable_fields)Útool_batch_fieldsr   r   Úvalid_tool_namesrv   Úargs_repairedFT)r‹   r|   rŒ   Ú	call_roleÚprimaryÚissuez-Shared-metrics tool-call quality not recorded©Úexc_info)Úrelay_shared_metricsr¤   r¥   Úshared_metrics_signalsr¦   Úshared_metrics_connectorsr§   r   ÚgetattrÚ	frozensetrˆ   r‚   r   ÚTOOL_BATCH_MARKry   rž   rz   Ú	argumentsÚidÚMODEL_TOOL_QUALITY_MARKÚTOOL_UNAVAILABLE_MARKÚ	ExceptionÚloggerÚdebug)r    r¡   r¢   r¤   r¥   r¦   r§   r'   r‹   r|   ÚbatchÚtcr…   r¬   Úunavailables   &&&            r   Úrecord_tool_call_qualityr¿   �   sR  € ðUßFç¡§¢ÙÝCÝ@ÜœG E¨:°tÓ<¼gÀeÈWÐVZÓ>[Ó\ˆÜ˜eÐ%7¸Ó>×MÐMÄ)Ã+ˆÜ#¤G¨E°7¸DÓ$AÓBˆÜ˜*Ó%ˆ
Ù& uÓ9Ð9ˆEÒFÙ¤× 8Ñ 8¸%Ô@ÛˆBØ—‘ˆBÜ#Ø—‘˜Ÿ™°;Ü˜B› <Ñ/×^Ð^´7¸2¸ÐPUÓ3VÐZ^Ð3^ôˆEñ  ¤× @Ñ @ÐBsÀUÐBsÈKÐYbÐdkÐmrÑBsÔtÙ6°u¿g¹gÀuÓTÐT�ÔaÙ#¤H×$BÑ$BÀKÖPó øô ô UÜ�‰ÐDÈtˆ×TðUús"   ‚E ’E ¡DE ÅE Å"FÆFÚ
session_idr    r   r   Úhermes_homeÚturnsc               ó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   rÀ   r   r    r   r   rÁ   rÂ   r@   r   rD   r   )r   s   "r   r   r   ¿   sN   € ÷ .ñ .Øð.Ø #ð.Ø36ð.ØILð.Ø\_ð.àð.à$'ð.ð 
ñ.r   c               ó,  € Rp V'       d   ^ RI Hp V! \        V4      4      p^RIHp	Hp
 V \        P                  9  g   V	! 4       '       g    Ve   ^ RI Hp V! V4       R# R# Ve1   \        VRV4      \        VRV4      rC\        VRR4      ;'       g    TpT
! T \        T;'       g    R4      \        W44      V4       Ve   ^ RI Hp V! V4       R# R#   \         d    \        P                  R	T R
R7        L;i ; i  Te   ^ RI Hp T! T4       i i ; i)a±  Count one user friction action against the model that produced the session's last turn.
``turns``: how many turns an /undo removed (their tokens count as wasted).

Falls back to ``agent`` (or ``provider``/``model``) when this process never saw the session's
turns (restart, remote compute host). ``hermes_home`` binds the owning profile for callers that
run outside it (multiplexed gateway, Desktop sessions of a secondary profile).
N)Úset_hermes_home_override)r¤   Úrecord_session_friction)Úreset_hermes_home_overrider   r   rÀ   Ú z'Shared-metrics %s friction not recordedTr­   )Úhermes_constantsrÅ   r   r¯   r¤   rÆ   r   r*   rÇ   r²   r   r¹   rº   r»   )r&   rÀ   r    r   r   rÁ   rÂ   ÚtokenrÅ   r¤   rÆ   rÇ   s   &$$$$$$     r   Úrecord_model_frictionrË   ¿   s  € ð €Eð.ßÝAá,¬S°Ó-=Ó>ˆEßJàœ×2Ñ2Ô2¹'¿)º)Øð ÒÝCá& uÖ-ñ ð ÒÜ% e¨Z¸ÓBÄGÈEÐSZÐ\aÓDb�eÜ  ¨°dÓ;×IÐI¸zˆJÙ ¬¨J×,<Ð,<¸"Ó(=¼{È8Ó?[Ð]bÔcð ÒÝCá& uÖ-ñ øô ô WÜ�‰Ð>ÀÐQUˆÖVðWûð ÒÝCá& uÕ-ð ús1   „AC Á$AC Â)C Ã#C;Ã8C> Ã:C;Ã;C> Ã>Dl    XŽp7 ))i }  Últ_32k)i ô Ú32k_to_128k)i è Ú128k_to_256k)i@B Ú
256k_to_1m>   r¼   Ú	delegatedÚ
backgroundÚscheduled_task)!rl   Ú
__future__r   r˜   ÚloggingÚdataclassesr   Útypingr   r   rÈ   r   r   r   rc   Ú	getLoggerrh   rº   r[   r"   r³   rN   rs   r   r$   r+   r6   r8   rt   rˆ   rž   r¿   rË   r   r   r   Ú<module>rØ      sä   ðñõ #ã Û Ý !ß  å 1Ý .à	×	Ò	˜8Ó	$€ð &Ð ðÐ ñ !Ð"4Ð6IÐ!JÓKÐ á#Ò$ZÓ[Ð õNõ[õ
Dõfð ÷6
ð 6
ó ð6
õr`õ	õ.õ2UðD.Ø&*ð.Ø9=ð.ØOSð.Øbfð.àð.à*+÷.ñ .r   