+
    iHàjt2  ã                   ón   € R t ^ RIt^ RIHtHt ^ RIHt ^ RI	H
t
 Rt^<tR R ltR R lt ! R	 R
4      tR# )aA  Provider reasoning-parameter policy for ``AIAgent``.

When ``reasoning`` extra_body is safe to send, LM Studio / Ollama / GitHub Models capability probes,
``reasoning_content`` echo families, and strict-API tool-call sanitising.
Extracted from ``run_agent.py``; every method resolves through ``AIAgent``'s MRO unchanged.
N)ÚforwardÚforward_static)Úmatches_reasoning_echo_family)Úbase_url_host_matchesc                ó$   € V ^8„  d   QhR\         /# )é   Ú
cache_attr)Ústr)Úformats   "Ú;/home/ubuntu/.hermes/hermes-agent/agent/reasoning_params.pyÚ__annotate__r      s   € ÷ ñ ¤Sñ ó    c           	     óº  € \        WR4      pVf   / p\        WV4       V P                  V P                  3pVP	                  V4      pVe:   Vw  r‰V! V4      '       g&   \
        P                  ! 4       V	,
          \        8  d   V#  V! V P                  V P                  \        V RR4      4      pV\
        P                  ! 4       3WV&   V#   \         d    Tp L*i ; i)zŸ``probe(model, base_url, api_key)`` once per (model, base_url); ``unknown`` is what a raising probe
yields, ``definitive(value)`` decides permanent vs 60s TTL.NÚapi_keyÚ )	ÚgetattrÚsetattrÚmodelÚbase_urlÚgetÚtimeÚ	monotonicÚ_PROBE_TTL_SÚ	Exception)
Úagentr   ÚprobeÚunknownÚ
definitiveÚcacheÚkeyÚcachedÚvalueÚtss
   &&&&&     r   Ú_cached_prober#      sÇ   € ô �E tÓ,€EØ‚}ØˆÜ� 5Ô)Ø�;‰;˜Ÿ™Ð
'€CØ�Y‰Y�s‹^€FØÒØ‰	ˆÙ�e×Ò¤§¢Ó!1°BÕ!6¼,Ô FØˆLðÙ�e—k‘k 5§>¡>´7¸5À)ÈRÓ3PÓQˆð œŸšÓ)Ð*€E�JØ€Løô ô ØŠðús   Â)C
 Ã
CÃCc                ó2   € V ^8„  d   QhR\         R,          /# ©r   ÚreturnN©Údict)r
   s   "r   r   r   .   s   € ÷ $ñ $¤d¨T¥kñ $r   c                ó  € \        V RR4      R8w  d   R# \        \        V RR4      ;'       g    R4      p\        \        V RR4      ;'       g    R4      p ^ RIHp V! V4      pVe   VP	                  V4      MRpT'       g   R#  ^ RIHp T! YR	R
7      pTe   TP                  R	J d   R# \        T RR4      '       d   T P                  4       '       g   R# \        T4      #   \
         d     R# i ; i  \
         d    Rp Lmi ; i)uÑ  Reasoning config for a main-loop request whose ``agent.reasoning_effort`` is unset.

Asks the active provider profile (``ProviderProfile.default_reasoning_config``; the custom /
OpenAI-compatible profile answers medium) so a route's own default never silently applies â€”
kimi-k3 behind a relay defaults to ``max``, 3x the reasoning tokens of medium. Resolved at
request time, so ``/model`` and fallback activation re-evaluate it. None keeps the field off
the wire: a non chat-completions transport, a profile without a default (those decide inside
``build_api_kwargs_extras``), a model the catalog / ``model_overrides`` mark
``supports_reasoning: false``, or a local Ollama model whose ``/api/show`` lacks ``thinking``.
Úapi_modeNÚchat_completionsÚproviderr   r   )Úget_provider_profile)Úget_model_capabilitiesF)Úallow_networkÚ_ollama_num_ctx)r   r	   Ú	providersr-   Údefault_reasoning_configr   Úagent.models_devr.   Úsupports_reasoningÚ _ollama_supports_thinking_cachedr(   )r   r,   r   r-   ÚprofileÚdefaultr.   Úcapss   &       r   Úunset_reasoning_defaultr9   .   s  € ô ˆu�j $Ó'Ð+=Ô=ÙÜ”7˜5 *¨bÓ1×7Ð7°RÓ8€HÜ”˜˜w¨Ó+×1Ð1¨rÓ2€EðÝ2á& xÓ0ˆØ=DÒ=P�'×2Ñ2°5Ô9ÐVZˆ÷ ÙðÝ;á% hÀUÔKˆð Ò˜D×3Ñ3°uÓ<Ùô ˆuÐ'¨×.Ò.°u×7]Ñ7]×7_Ò7_ÙÜ�‹=Ðøô! ô Úðûô ô ØŠðús$   Á%C" ÂC4 Ã"C1Ã0C1Ã4DÄDc                   ón  a € ] tR t^Ut o RtV 3R lR ltV 3R lR ltV 3R lR ltV 3R lR	 lt]	! R
R4      t
R tV 3R lR ltV 3R lR lt]V 3R lR l4       tV 3R lR ltV 3R lR ltV 3R lR lt]	! RR4      t]	! RR4      t]R%RRRR/V 3R lR  lll4       t]! RR!4      tV 3R" lR# ltR$tV tR# )&ÚReasoningParamsMixinzBReasoning-parameter gating and echo policy (see module docstring).c                ó    <€ V ^8„  d   QhRS[ /# ©r   r&   ©Úbool)r
   Ú__classdict__s   "€r   r   Ú!ReasoningParamsMixin.__annotate__X   s   ø€ ÷ !Zñ !Z±ñ !Zr   c                ó8  a€ V P                   p\        VR4      '       g   \        VR4      '       d   R# \        VR4      '       g   \        VR4      '       d#    ^ RIHp \	        V! V P
                  4      4      # V P                  ;'       g    RP                  4       P                  4       R	8X  dQ   \        ;QJ d*    R
 V P                  4        4       F  '       g   K   R# 	  R# ! R
 V P                  4        4       4      # \        VR4      '       d   V P                  4       # V P                  4       '       d   \        VR4      '       d   R#  ^ RIHpHp V! V P
                  4      pVf   V! 4        Te   \	        TP#                  R4      4      # T P
                  ;'       g    RP                  4       o\        ;QJ d#    T3R l\$         4       F  '       g   K   R# 	  R# ! T3R l\$         4       4      #   \         d     R# i ; i  \         d    Rp L¥i ; i)zÉTrue when reasoning extra_body is safe to send: OpenRouter forwards unknown extra_body upstream and
some routes 400 on ``reasoning``, so gate to known reasoning-capable families and direct Nous Portal.znousresearch.comzai-gateway.vercel.shTzmodels.github.aizgithubcopilot.com)Úgithub_model_reasoning_effortsFr   Úlmstudioc              3   ó>   "  € T F  q;'       d    VR 8g  x € K  	  R# 5i)ÚoffN© )Ú.0Úopts   & r   Ú	<genexpr>ÚFReasoningParamsMixin._supports_reasoning_extra_body.<locals>.<genexpr>g   s   é € ÐaÑ7`°×+Ð+˜s e™|Ô+Ó7`ùs   ‚�z
ollama.comzapi.mistral.ai)Ú'openrouter_model_reasoning_capabilitiesÚ$warm_openrouter_reasoning_caps_asyncNr4   c              3   óF   <"  € T F  pSP                  V4      x € K  	  R # 5i©N)Ú
startswith)rH   Úprefixr   s   & €r   rJ   rK   y   s!   øé € ÐYÑ:X°�5×#Ñ# F×+Ð+Ó:Xùs   ƒ!)Ú_base_url_lowerr   Úhermes_cli.modelsrC   r?   r   r   r,   ÚstripÚlowerÚanyÚ"_lmstudio_reasoning_options_cachedr5   Ú_is_openrouter_urlÚ hermes_cli.models_reasoning_capsrL   rM   r   Ú_OPENROUTER_REASONING_PREFIXES)ÚselfÚurlrC   rL   rM   r8   r   s   &     @r   Ú_supports_reasoning_extra_bodyÚ3ReasoningParamsMixin._supports_reasoning_extra_bodyX   s¸  ø€ ð ×"Ñ"ˆÜ  Ð&8×9Ò9Ô=RÐSVÐXn×=oÒ=oÙÜ  Ð&8×9Ò9Ô=RÐSVÐXk×=lÒ=lðÝLäÑ:¸4¿:¹:ÓFÓGÐGð �M‰M×Ð˜R×&Ñ&Ó(×.Ñ.Ó0°JÔ>ç“3Ña°t×7^Ñ7^Ô7`Óa—3”3Ða’3Ða�3Ña°t×7^Ñ7^Ô7`ÓaÓaÐaÜ   l×3Ò3à×8Ñ8Ó:Ð:Ø×&Ñ&×(Ò(Ô,AÀ#ÐGW×,XÒ,XÙð	÷ GÙ:¸4¿:¹:ÓFˆDØŠ|Ù4Ô6ð ÒÜ˜Ÿ™Ð!5Ó6Ó7Ð7Ø—‘×!Ð!˜r×(Ñ(Ó*ˆß‹sÔYÕ:XÓY�sŒsÐYŠsÐYˆsÔYÕ:XÓYÓYÐYøô- ô Úðûô" ô 	ØŠDð	ús$   Á G7 Å%H	 Ç7HÈHÈ	HÈHc                ó0   <€ V ^8„  d   QhRS[ S[,          /# r=   )Úlistr	   )r
   r@   s   "€r   r   rA   {   s   ø€ ÷ kñ k±D¹µIñ kr   c                ó\   €  ^ RI Hp \        T RT. \        4      #   \         d    . u # i ; i)zjLM Studio's published reasoning ``allowed_options`` (gate + clamp so toggle models don't 400 on ``high``).)Ú lmstudio_model_reasoning_optionsÚ_lm_reasoning_opts_cache)Úhermes_cli.models_localrb   r   r#   r?   )r[   rb   s   & r   rW   Ú7ReasoningParamsMixin._lmstudio_reasoning_options_cached{   s9   € ð	ÝPô ˜TÐ#=Ð?_ÐacÔeiÓjÐjøô ô 	ØŠIð	ús   ‚ ›+ª+c                ó    <€ V ^8„  d   QhRS[ /# r=   r>   )r
   r@   s   "€r   r   rA   ƒ   s   ø€ ÷ Bñ B±$ñ Br   c           	     óf   €  ^ RI Hp \        \	        T RTRR 4      4      #   \         d     R# i ; i)zITrue only if Ollama's ``/api/show`` declares the ``thinking`` capability.)Úollama_model_supports_thinkingFÚ_ollama_thinking_cacheNc                 ó
   € V R J# rO   rG   )Úvs   &r   Ú<lambda>ÚGReasoningParamsMixin._ollama_supports_thinking_cached.<locals>.<lambda>‰   s   € ÐrsÐ{Ñrr   )rd   rh   r   r?   r#   )r[   rh   s   & r   r5   Ú5ReasoningParamsMixin._ollama_supports_thinking_cachedƒ   sE   € ð	ÝNô ”M $Ð(@ÐB`ÐbfÑhó  Aó  Bð  	Bøô ô 	Úð	ús   ‚! ¡0¯0c                ó.   <€ V ^8„  d   QhRS[ R,          /# r%   r'   )r
   r@   s   "€r   r   rA   ‹   s   ø€ ÷ Wñ W±T¸Dµ[ñ Wr   c                ó.  €  ^ RI HpHp T! T P                  4      pT'       g   R# \        T P                  \        4      '       d   T P                  M/ pTP                  R4      RJ d   R# RT! TP                  R4      T4      /#   \         d     R# i ; i)zDFormat reasoning payload for GitHub Models/OpenAI-compatible routes.)Úclamp_github_reasoning_effortrC   NÚenabledFÚeffort)	rS   rq   rC   r   r   Ú
isinstanceÚreasoning_configr(   r   )r[   rq   rC   Ú	supportedÚcfgs   &    r   Ú#_github_models_reasoning_extra_bodyÚ8ReasoningParamsMixin._github_models_reasoning_extra_body‹   s„   € ð	ßgñ 3°4·:±:Ó>ˆ	ßÙä'1°$×2GÑ2GÌ×'NÒ'Nˆd×#Ò#ÐTVˆØ�7‰7�9Ó Ó&ÙØÑ7¸¿¹ÀÓ8IÈ9ÓUÐVÐVøô ô 	Úð	ús   ‚B ÂBÂBzagent.chat_completion_helpersÚbuild_assistant_messagec           	     óŽ  € ^ RI HpHp V! V 4      p\        V RR4      V P                  V P
                  \        V RV P                  4      V P                  4       V3p\        V RR4      pVe   V^ ,          V8X  d
   V^,          # V! V^ ,          V P                  V P
                  V P                  V^,          VR7      pWF3V n        V# )um  Reasoning replay decision for the active route (``message_sanitization.reasoning_replay_route``).

Cached per (api_mode, provider, model, base_url, opt-in, rejected keys) â€” called many times
per turn â€” and recomputed after ``switch_model()`` / fallback activation or a recorded
field rejection, the only events allowed to change the replayed bytes mid-session.
)Úreasoning_replay_routeÚrejected_reasoning_carriersr*   NrR   Ú_reasoning_route_cache)Úecho_opt_inÚrejected)	Úagent.message_sanitizationr|   r}   r   r,   r   r   Ú_reasoning_echo_opt_inr~   )r[   r|   r}   r€   r   r    Úroutes   &      r   Ú_reasoning_replay_routeÚ,ReasoningParamsMixin._reasoning_replay_route�   s¸   € ÷ 	cá.¨tÓ4ˆÜ�t˜Z¨Ó.°·±¸t¿z¹zÌ7ÐSWÐYjÐlp×lyÑlyÓKzØ×*Ñ*Ó,¨hð8ˆä˜Ð7¸Ó>ˆØÒ &¨¥)¨sÔ"2Ø˜!•9ÐÙ& s¨1¥v¨t¯}©}¸d¿j¹jÈ$Ï-É-Ø36°qµ6ÀHôNˆà'* lˆÔ#Øˆr   c                ó    <€ V ^8„  d   QhRS[ /# r=   r>   )r
   r@   s   "€r   r   rA   ±   s   ø€ ÷ 2ñ 2©tñ 2r   c                ó6   € V P                  4       P                  # )a  True for the must-echo tier: DeepSeek / Kimi / MiMo thinking 400 on a replayed tool-call turn
without a non-empty ``reasoning_content`` (#15250, #17400), plus a ``model.reasoning_echo`` opt-in
for gateways proxying them. Never true on a route that does not read the field.)r„   Úpad©r[   s   &r   Ú_needs_thinking_reasoning_padÚ2ReasoningParamsMixin._needs_thinking_reasoning_pad±   s   € ð ×+Ñ+Ó-×1Ñ1Ð1r   c                ó    <€ V ^8„  d   QhRS[ /# r=   r>   )r
   r@   s   "€r   r   rA   ·   s   ø€ ÷ Bñ B©ñ Br   c                ó.   € \        \        V RR4      4      # )u  ``model.reasoning_echo``: treat the *current* provider as must-echo (pad tool-call turns) â€” for
gateways proxying DeepSeek/Kimi/MiMo that the host rules miss. Replay itself is on by default;
fallback activation swaps the flag and ``restore_primary_runtime()`` restores it.Ú_reasoning_echo_flagF)r?   r   r‰   s   &r   r‚   Ú+ReasoningParamsMixin._reasoning_echo_opt_in·   s   € ô ”G˜DÐ"8¸%Ó@ÓAÐAr   c                ó    <€ V ^8„  d   QhRS[ /# r=   r>   )r
   r@   s   "€r   r   rA   ¾   s   ø€ ÷ ñ ©dñ r   c                 ó¤   €  ^ RI Hp  \        V ! 4       P                  R4      ;'       g    / P                  R4      4      #   \         d     R# i ; i)z>Read ``model.reasoning_echo`` from config; False on any error.©Úload_config_readonlyr   Úreasoning_echoF)Úhermes_cli.configr“   r?   r   r   r’   s    r   Ú _read_reasoning_echo_from_configÚ5ReasoningParamsMixin._read_reasoning_echo_from_config½   sJ   € ð	Ý>ÜÑ-Ó/×3Ñ3°GÓ<×BÐBÀ×GÑGÐHXÓYÓZÐZøÜô 	Úð	ús   ‚'A  ªA  Á AÁAc                ó    <€ V ^8„  d   QhRS[ /# r=   r>   )r
   r@   s   "€r   r   rA   É   s   ø€ ÷ Yñ Y©Dñ Yr   c                óF   € \        RV P                  RV P                  4      # )z@True when the current provider is Kimi / Moonshot thinking mode.ÚkimiN)r   r,   r   r‰   s   &r   Ú_needs_kimi_tool_reasoningÚ/ReasoningParamsMixin._needs_kimi_tool_reasoningÉ   s   € ä,¨V°T·]±]ÀDÈ$Ï-É-ÓXÐXr   c                ó    <€ V ^8„  d   QhRS[ /# r=   r>   )r
   r@   s   "€r   r   rA   Í   s   ø€ ÷ sñ s±ñ sr   c                óŠ   € \        RV P                  ;'       g    RP                  4       V P                  V P                  4      # )a  True when the current provider is DeepSeek thinking mode (omitting the echo is an HTTP 400).

DeepSeek V4 thinking mode requires ``reasoning_content`` on every assistant tool-call turn; omitting
it causes HTTP 400 when the message is replayed in a subsequent API request (#15250).
Údeepseekr   ©r   r,   rU   r   r   r‰   s   &r   Ú_needs_deepseek_tool_reasoningÚ3ReasoningParamsMixin._needs_deepseek_tool_reasoningÍ   s8   € ô -¨Z¸$¿-¹-×:MÐ:MÈ2×9TÑ9TÓ9VÐX\×XbÑXbÐdh×dqÑdqÓrÐrr   c                ó    <€ V ^8„  d   QhRS[ /# r=   r>   )r
   r@   s   "€r   r   rA   Õ   s   ø€ ÷ oñ o©Dñ or   c                óŠ   € \        RV P                  ;'       g    RP                  4       V P                  V P                  4      # )z<True when the current provider is Xiaomi MiMo thinking mode.Úmimor   r    r‰   s   &r   Ú_needs_mimo_tool_reasoningÚ/ReasoningParamsMixin._needs_mimo_tool_reasoningÕ   s6   € ä,¨V°d·m±m×6IÐ6IÀr×5PÑ5PÓ5RÐTX×T^ÑT^Ð`d×`mÑ`mÓnÐnr   zagent.agent_runtime_helpersÚcopy_reasoning_content_for_apiÚ#reapply_reasoning_echo_for_providerNr   r,   c          
      ób   <€ V ^8„  d   QhRS[ RS[R,          RS[R,          RS[R,          RS[ /# )r   Úapi_msgr   Nr   r,   r&   )r(   r	   )r
   r@   s   "€r   r   rA   Þ   sA   ø€ ÷ ñ ±Tð Á#ÈÅ*ð ÑbeÐhlÕblð Ù69¸DµjðÙLPñr   c               ó‚  € V P                  R4      p\        V\        4      '       g   V # ^ RIHp V! WV4      pRR0V'       d   \        4       MR0,          pV UU	U
u. uFG  p\        V\        4      '       d-   VP                  4        U	U
u/ uF  w  ršW—9  g   K  WšbK  	  up
p	MTNKI  	  up
p	pV R&   V # u up
p	i u up
p	pi )aG  Strip Codex Responses fields from tool_calls for strict Chat Completions APIs (Mistral, Fireworks
400/422 on unknown fields). ``extra_content`` (Gemini thought_signature) is kept only on Gemini routes
(model family, Gemini host or provider). Builds new dicts so the internal history keeps the Codex
fields for a later fallback.Ú
tool_calls)Ú!_model_consumes_thought_signatureÚcall_idÚresponse_item_idÚextra_content)r   rt   r`   Ú!agent.transports.chat_completionsr®   Úsetr(   Úitems)r«   r   r   r,   r­   r®   Úkeep_signaturerT   ÚtcÚkrk   s   &&$$       r   Ú#_sanitize_tool_calls_for_strict_apiÚ8ReasoningParamsMixin._sanitize_tool_calls_for_strict_apiÝ   s´   € ð —[‘[ Ó.ˆ
Ü˜*¤d×+Ò+ØˆNÝWÙ:¸5ÈHÓUˆØÐ.Ð/¿N´3´5ÐQ`ÐPaÕbˆá+5õ!7Ù+5 Rô U_Ð_aÔcg×ThÒTh°2·8±8´:Ô!P±:©4¨1ÀÁ¤$ !¢$±:Ó!PÐnpÒ!pÙ+5ó!7ˆ�Ñàˆùó "Qùô !7s   Á.B:Â
B4ÂB4Â 
B:Â4B:Úsanitize_tool_call_argumentsc                ó    <€ V ^8„  d   QhRS[ /# r=   r>   )r
   r@   s   "€r   r   rA   ð   s   ø€ ÷ 2ñ 2©Tñ 2r   c                ó    € V P                   R8g  # )zgTrue for every non-Codex API: Codex Responses fields are not Chat Completions schema and 400 elsewhere.Úcodex_responses)r*   r‰   s   &r   Ú_should_sanitize_tool_callsÚ0ReasoningParamsMixin._should_sanitize_tool_callsð   s   € à�}‰}Ð 1Ñ1Ð1r   )r~   rO   )Ú__name__Ú
__module__Ú__qualname__Ú__firstlineno__Ú__doc__r]   rW   r5   rx   Ú_forwardÚ_build_assistant_messager„   rŠ   r‚   Ústaticmethodr–   r›   r¡   r¦   Ú_copy_reasoning_content_for_apiÚ$_reapply_reasoning_echo_for_providerr¸   Ú_forward_staticÚ_sanitize_tool_call_argumentsr¾   Ú__static_attributes__Ú__classdictcell__)r@   s   @r   r;   r;   U   sÿ   ø‡ € ÙL÷!Zð !Z÷Fkð k÷Bð B÷Wð Wñ   (Ð(GÐIbÓcÐò÷(2ð 2÷Bð Bð ÷ó ð÷Yð Y÷sð s÷oð oñ '/Ð/LÐNnÓ&oÐ#á+3Ð4QÐSxÓ+yÐ(àñÐosð ØCG÷ò ó ðñ  %4Ð4QÐSqÓ$rÐ!÷2ö 2r   r;   )	z	deepseek/z
anthropic/zopenai/zx-ai/zgoogle/gemini-2zgoogle/gemma-4z
qwen/qwen3z
tencent/hyzxiaomi/)rÄ   r   Úagent.lazy_forwardr   rÅ   r   rÊ   r�   r   Úutilsr   rZ   r   r#   r9   r;   rG   r   r   Ú<module>rÐ      s>   ðñó ç UÝ DÝ 'ð"Ð ð €õõ*$÷N]2ó ]2r   