+
    iHàje  ã                  ó�   a € 0 t $ R t^ RIHt ^ RIt^ RIHtHt ]P                  ! ]	4      t
RtR]R&   RtR R ltR	 R
 ltR R ltR# )a	  Per-response *served model* capture for routing proxies (#54864).

A LiteLLM-style proxy answers with the configured alias in the body's ``model`` field and puts
the deployment it really routed to in a response header (``x-litellm-model-id``, else the
upstream ``x-litellm-model-api-base``). The OpenAI SDK's parsed objects drop headers, so the
capture rides an ``httpx`` response hook on the client Hermes builds for the agent; it stores
the header onto ``agent.last_served_model`` (``None`` when the response carried none, so a
value never outlives the request that produced it). Consumers: ``agent/turn_finalizer.py``
(result ``served_model`` / ``requested_model``) and the opt-in gateway footer field
``served_model`` (``gateway/runtime_footer.py``). Fail-open everywhere.
)ÚannotationsN)ÚAnyÚOptionalztuple[str, ...]ÚSERVED_MODEL_HEADERSÚ_hermes_served_model_hookc               ó    € V ^8„  d   QhRRRR/# )é   Úheadersr   ÚreturnzOptional[str]© )Úformats   "Ú7/home/ubuntu/.hermes/hermes-agent/agent/served_model.pyÚ__annotate__r      s   € ÷ ñ  sð ¨}ñ ó    c                ó¶   € V e   \        V R4      '       g   R# \         F6  pV P                  V4      pVR9  g   K  \        V4      P	                  4       u # 	  R# )z1First non-empty served-model header, or ``None``.NÚget)NÚ )Úhasattrr   r   ÚstrÚstrip)r	   ÚnameÚvalues   &  r   Úserved_model_from_headersr      sN   € à‚œg g¨u×5Ò5Ùß$ˆØ—‘˜DÓ!ˆØ˜
Ö"Ü�u“:×#Ñ#Ó%Ò%ñ %ñ r   c               ó$   € V ^8„  d   QhRRRRRR/# )r   Úagentr   Úclientr
   ÚNoner   )r   s   "r   r   r   #   s&   € ÷ Iñ I¨ð I°Sð I¸Tñ Ir   c                óî  a € \        VRR4      p\        VRR4      p\        V\        4      '       g   R# \        ;QJ d,    R VP	                  RR4       4       F  '       g   K   RM!	  RM! R VP	                  RR4       4       4      '       d   R# R V 3R	 llp\        V\        R4        / VCR. VP	                  RR4      OVN/CVn        R#   \         d    \        P                  R
RR7        R# i ; i)zURegister the response hook on *client*'s ``httpx`` transport (idempotent per client).Ú_clientNÚevent_hooksc              3  óD   "  € T F  p\        V\        R 4      x € K  	  R# 5i)FN)ÚgetattrÚ
_HOOK_MARK)Ú.0Úhs   & r   Ú	<genexpr>Ú/install_served_model_capture.<locals>.<genexpr>)   s   é € Ð
LÑ2K¨QŒ7�1”j %×(Ð(Ó2Kùs   ‚ ÚresponseTFc               ó    € V ^8„  d   QhRRRR/# )r   r'   r   r
   r   r   )r   s   "r   r   Ú2install_served_model_capture.<locals>.__annotate__,   s   € ÷ Oñ O˜sð O tñ Or   c                óä   <€  ^È\        \        V R^ 4      4      u;8:  d   R8  d"   M R# \        \        V RR4      4      Sn        R# R#   \         d    \
        P                  RRR7        R# i ; i)éÈ   Ústatus_codei,  r	   Nz#served-model header capture skippedT©Úexc_info)Úintr!   r   Úlast_served_modelÚ	ExceptionÚloggerÚdebug)r'   r   s   &€r   Ú_on_responseÚ2install_served_model_capture.<locals>._on_response,   sg   ø€ ð	OØ”cœ' (¨M¸1Ó=Ó>ÖDÀ×DÐDÜ*CÄGÈHÐV_ÐaeÓDfÓ*g�Ö'ñ Eøäô 	OÜ�L‰LÐ>ÈˆL×Nð	Oús   ƒ%A	 ªA	 Á	"A/Á.A/z!served-model hook install skippedr-   r   )r!   Ú
isinstanceÚdictÚanyr   Úsetattrr"   r   r1   r2   r3   )r   r   Úhttp_clientÚhooksr4   s   f&   r   Úinstall_served_model_capturer<   #   s×   ø€ ä˜& )¨TÓ2€KÜ�K °Ó5€EÜ�eœT×"Ò"Ùß
ƒsÑ
L°%·)±)¸JÈÔ2KÓ
L‡s‡s‚sÑ
L°%·)±)¸JÈÔ2KÓ
L×LÒLÙ÷Oð Oô ˆLœ* dÔ+ðIà"c UÐ"c¨JÐ8b¸%¿)¹)ÀJÐPRÓ:SÐ8bÐUaÐ8bÑ"cˆÖøÜô IÜ�‰Ð8À4ˆ×HðIús   Â+!C Ã"C4Ã3C4c               ó    € V ^8„  d   QhRRRR/# )r   r   r   r
   zdict[str, Optional[str]]r   )r   s   "r   r   r   ;   s   € ÷ 	Jñ 	J˜sð 	JÐ'?ñ 	Jr   c                ó`  € \        V RR4      pV P                  pV'       g   \        V RR4      '       dl   \        \        V RR4      ;'       g    / P                  R4      ;'       g    R4      P	                  4       pV'       d   W0P                  8w  d   Y0P                  rRTR	T;'       g    R/# )
u¬   ``requested_model`` / ``served_model`` for the turn result: the proxy header when the
last response carried one, else Hermes' own fallback route (primary â†’ active model).r0   NÚ_fallback_activatedFÚ_primary_runtimeÚmodelr   Úrequested_modelÚserved_model)r!   rA   r   r   r   )r   ÚservedÚ	requestedÚprimarys   &   r   Úresult_model_fieldsrG   ;   s‘   € ô �UÐ/°Ó6€FØ—‘€Iß”g˜eÐ%:¸E×BÒBÜ”w˜uÐ&8¸$Ó?×EÐEÀ2×JÑJÈ7ÓS×YÐYÐWYÓZ×`Ñ`Óbˆß�w§+¡+Ô-Ø '¯©�vØ˜y¨.¸&¿.¸.ÀDÐIÐIr   )zx-litellm-model-idzx-litellm-model-api-base)Ú__conditional_annotations__Ú__doc__Ú
__future__r   ÚloggingÚtypingr   r   Ú	getLoggerÚ__name__r2   r   Ú__annotations__r"   r   r<   rG   )rH   s   @r   Ú<module>rP      sG   øðô
õ #ã ß  à	×	Ò	˜8Ó	$€à(ZÐ �oÓ ZØ(€
õõI÷0	Jr   