+
    iHàj,  ã                  óî   a € 0 t $ R t^ RIHt ^ RIt^ RIHtHtHt ^ RI	H
t
 ]P                  ! ]4      tRt]! 4       tR]R&   0 RmtR R	 ltR
 R ltR R ltR R ltR R lt0 RmtR R ltRR R lltR# )uÏ  Reasoning floor for auxiliary requests: when a route refuses to switch reasoning OFF, step it UP.

Aux lanes that want speed over thought (title generation: ``max_tokens=64``, JSON body) send the
provider's thinking-off encoding â€” top-level ``reasoning_effort: "none"`` on the custom profile,
``extra_body.reasoning: {"enabled": false}`` on OpenRouter-shaped relays, ``_reasoning_config`` on the
Anthropic Messages adapters. Some endpoints understand the field but refuse the disable ("Reasoning is
mandatory for this endpoint and cannot be disabled" â€” the Nous Portal on gpt-6-astra); before this
module every title call there 400'd and the session stayed untitled.

The recovery is a *step up*, not a strip: the same request goes out again at the lowest effort every
reasoning wire accepts (``low``; ``minimal`` is rejected by o-series and Claude), and the (route, model)
pair is memoised so the next disabled-reasoning aux call on it starts at the floor instead of burning
the guaranteed 400 first. Dropping the field would also succeed once, but it says nothing about the
next call and hands the effort choice back to the provider default (often ``medium`` or higher, the
opposite of what a thinking-off caller asked for).
)ÚannotationsN)ÚAnyÚDictÚOptional)ÚurlparseÚlowzset[tuple[str, str]]Ú_FLOORED_ROUTESc               ó$   € V ^8„  d   QhRRRRRR/# )é   ÚproviderúOptional[str]Úbase_urlÚreturnÚstr© )Úformats   "ÚD/home/ubuntu/.hermes/hermes-agent/agent/auxiliary_reasoning_floor.pyÚ__annotate__r   !   s&   € ÷ bñ b˜ð b°-ð bÀCñ bó    c                óâ   € \        T;'       g    R4      P                  ;'       g    RP                  4       ;'       g2    \        T ;'       g    R4      P	                  4       P                  4       # )u¯   Endpoint host:port when known (a base_url override turns a named provider into ``custom``), else
the provider name â€” the same key shape ``auxiliary_structured_output`` uses.Ú )r   ÚnetlocÚlowerr   Ústrip)r   r   s   &&r   Ú
_route_keyr   !   sQ   € ô �X—^�^ Ó$×+Ñ+×1Ð1¨r×8Ñ8Ó:×aÐa¼cÀ(Ç.À.ÈbÓ>Q×>WÑ>WÓ>Y×>_Ñ>_Ó>aÐar   c               ó    € V ^8„  d   QhRRRR/# )r
   Úreasoning_configr   r   Úboolr   )r   s   "r   r   r   '   s   € ÷ [ñ [ 3ð [¨4ñ [r   c                óX   € \        V \        4      ;'       d    V P                  R 4      RJ # )ÚenabledF)Ú
isinstanceÚdictÚget©r   s   &r   Ú_is_disabledr$   '   s*   € ÜÐ&¬Ó-×ZÐZÐ2B×2FÑ2FÀyÓ2QÐUZÐ2ZÐZr   c               ó    € V ^8„  d   QhRRRR/# )r
   r   r   r   údict[str, Any]r   )r   s   "r   r   r   +   s   € ÷ ñ ¨Sð °^ñ r   c                ó<   € \        V 4      '       d   RRR\        /# V # )z]The caller's disabled ``reasoning_config`` lifted to the floor; anything else returned as-is.r   TÚeffort)r$   ÚREASONING_FLOOR_EFFORTr#   s   &r   Úfloor_reasoning_configr*   +   s$   € äÐ$×%Ò%Ø˜4 Ô+AÐBÐBØÐr   c               ó    € V ^8„  d   QhRRRR/# )r
   Úkwargsr&   r   zOptional[dict[str, Any]]r   )r   s   "r   r   r   2   s   € ÷ &ñ & ð &Ð4Lñ &r   c                ó   € Rp\        V 4      p\        VP                  RR4      4      P                  4       P	                  4       \
        9   d   \        VR&   Rp\        VP                  R4      4      '       d   \        VR,          4      VR&   RpVP                  R4      p\        V\         4      '       dŽ   VP                  R4      p\        V4      '       gW   \        V\         4      '       dV   \        VP                  RR4      4      P                  4       P	                  4       \
        9   d   / VCRR	RR\        //CVR&   RpV'       d   V# R
# )a+  Copy of *kwargs* with every thinking-OFF encoding lifted to ``REASONING_FLOOR_EFFORT``:
top-level ``reasoning_effort``, ``extra_body.reasoning`` (OpenRouter shape) and the adapter's private
``_reasoning_config``. ``None`` when nothing was disabled, so the ladder never re-sends an unchanged
request.FÚreasoning_effortr   TÚ_reasoning_configÚ
extra_bodyÚ	reasoningr(   r   N)
r!   r   r"   r   r   Ú_DISABLED_EFFORTSr)   r$   r*   r    )r,   ÚchangedÚretryr0   r1   s   &    r   Úwith_reasoning_floorr5   2   s  € ð
 €GÜ�‹L€EÜ
ˆ5�9‰9Ð'¨Ó,Ó-×3Ñ3Ó5×;Ñ;Ó=ÔARÔRÜ$:ˆÐ Ñ!ØˆÜ�E—I‘IÐ1Ó2×3Ò3Ü%;¸EÐBUÕ<VÓ%WˆÐ!Ñ"ØˆØ—‘˜<Ó(€JÜ�*œd×#Ò#Ø—N‘N ;Ó/ˆ	Ü˜	×"Ò"Ü�y¤$×'Ò'¬C°	·±¸hÈÓ0KÓ,L×,RÑ,RÓ,T×,ZÑ,ZÓ,\Ô`qÔ,qà"r ZÐ"r°¸yÈ$ÐPXÔZpÐ>qÑ"rˆE�,ÑØˆGßˆ5Ð% Ð%r   c          
     ó,   € V ^8„  d   QhRRRRRRRRRR	/# )
r
   r   r   r   Úrejected_kwargsr&   ÚerrorÚBaseExceptionr   ÚNoner   )r   s   "r   r   r   J   s;   € ÷ cñ cØðcØ'4ðcØGUðcØ^kðcà	ñcr   c                óŠ   € \         P                  \        W4      \        VP	                  R4      ;'       g    R4      34       R# )z�Record that this route's ``rejected_kwargs["model"]`` refuses to disable reasoning (the ladder
calls this after the stepped-up retry succeeded).Úmodelr   N)r   Úaddr   r   r"   )r   r   r7   r8   s   &&&&r   Úremember_reasoning_floorr>   J   s6   € ô
 ×Ñœ HÓ7¼¸_×=PÑ=PÐQXÓ=Y×=_Ð=_Ð]_Ó9`ÐaÖbr   c               ó(   € V ^8„  d   QhRRRRRRRR/# )r
   r   r   r   r<   r   r   r   )r   s   "r   r   r   U   s*   € ÷ 0ñ 0 }ð 0Àð 0ÐVcð 0Ðhlñ 0r   c                ó6  € \        T ;'       g    R4      P                  4       P                  4       p\        T;'       g    R4      P                  ;'       g    RP                  4       p^ RIHp VR8X  g   VR8X  g   VP                  R4      '       d   VP                  VP                  rvM%V\        9   d   VP                  VP                  rvMR#  V! V4      pVf   V! 4        \        T;'       d    TP                  R4      4      #   \         d     R# i ; i)u‡  True when the route's ``/v1/models`` catalog (OpenRouter, Nous Portal) flags *model*
``reasoning.mandatory``. Cache-only â€” memory, then the disk mirror â€” so it never blocks; a cold
catalog is warmed in the background, and the mirror it writes answers every later call and process.
Without this an aux-only OpenRouter route (nothing else warms that catalog) paid the 400 in every
process.r   )Úmodels_reasoning_capsÚ
openrouterzopenrouter.aiz.openrouter.aiFÚ	mandatory)r   r   r   r   ÚhostnameÚ
hermes_clirA   ÚendswithÚ'openrouter_model_reasoning_capabilitiesÚ$warm_openrouter_reasoning_caps_asyncÚ_NOUS_PROVIDERSÚ!nous_model_reasoning_capabilitiesÚwarm_nous_reasoning_caps_asyncÚ	Exceptionr   r"   )	r   r   r<   Úprovider_normÚhostÚcaps_modÚlookupÚwarmÚcapss	   &&&      r   Ú_catalog_marks_mandatoryrS   U   sé   € ô ˜Ÿ˜ BÓ'×-Ñ-Ó/×5Ñ5Ó7€MÜ�X—^�^ Ó$×-Ñ-×3Ð3°×:Ñ:Ó<€DÝ<Ø˜Ô$¨°Ô(?À4Ç=Á=ÐQa×CbÒCbØ×GÑGÈ×IvÑIv‘Ø	œ/Ô	)Ø×AÑAÀ8×CjÑCj‘áðÙ�e‹}ˆØŠ<ÙŒFô �×.Ð.˜Ÿ™ +Ó.Ó/Ð/øô ô Úðús   ÃD	 Ä	DÄDc               ó0   € V ^8„  d   QhRRRRRRRRRRRR/# )	r
   r   r   r   r   r   r<   Útaskr   r   )r   s   "r   r   r   m   s>   € ÷ 4ñ 4Øð4Ø%2ð4Ø>Kð4ØTað4à
ð4ð 	ñ4r   c                ó@  € \        V 4      '       g   V # \        W4      \        T;'       g    R4      3\        9  d   \	        WV4      '       g   V # \
        P                  RT;'       g    R\        W4      ;'       g    RT;'       g    R\        4       \        V 4      # )u  *reasoning_config* lifted to the floor when this route+model is known to refuse a disable â€” learned
from an earlier 400 in this process, or flagged mandatory by the route's model catalog; unchanged
otherwise. Runs before the profile projection so every wire shape starts at the floor.r   zJAuxiliary %s: %s (%s) cannot disable reasoning; sending effort=%s up frontÚcallr   r<   )	r$   r   r   r   rS   ÚloggerÚinfor)   r*   )r   r   r   r<   rU   s   &&&&&r   Úknown_reasoning_floorrZ   m   s‘   € ô Ð(×)Ò)ØÐÜ�8Ó&¬¨E¯K¨K°RÓ(8Ð9ÄÔPÔYqØ˜E÷Zò Zð  ÐÜ
‡K�KØTØ�ˆ�œ
 8Ó6×DÐD¸*Àe×FVÐFVÈwÔXnôô "Ð"2Ó3Ð3r   >   Ú0ÚoffÚnoneÚfalseÚdisabled>   ÚnousÚnousresearchúnous-portal)N)Ú__conditional_annotations__Ú__doc__Ú
__future__r   ÚloggingÚtypingr   r   r   Úurllib.parser   Ú	getLoggerÚ__name__rX   r)   Úsetr   Ú__annotations__r2   r   r$   r*   r5   r>   rI   rS   rZ   )rc   s   @r   Ú<module>rm      sy   øðôõ  #ã ß &Ñ &Ý !à	×	Ò	˜8Ó	$€àÐ ñ ),«€Ð%Ó -â=Ð õbõ[õõ&õ0cò :€õ0÷04ñ 4r   