+
    lHàj  ã                   ó$  a € R t0 t R t^ RIHtHt ^ RIHt ^ RIHt R]	! R4      /t
] ^ k Rt] ^k Rt] ^k Rt] ^k R	t] ^k R
t] ^k R R lt]! RR7       ! R R4      4       t]! 4       t]t] ^k Rt] ^k Rt] ^k Rt] ^	k Rt] ^
k R R ltR# )zConfigurable budget constants for tool result persistence.
Per-tool resolution: pinned > config overrides > registry > default.)Ú	dataclassÚfield)ÚDict)ÚCHARS_PER_TOKENÚ	read_fileÚinfi † i@ iÜ  iPÃ  Úmcp_c                ó$   € V ^8„  d   QhR\         /# )é   Úreturn)Úint)Úformats   "Ú8/home/ubuntu/.hermes/hermes-agent/tools/budget_config.pyÚ__annotate__r      s   € ÷ )ñ )¤Sñ )ó    c                 ó8  €  ^ RI Hp  V ! 4       p\        V\        4      '       d   VP	                  R4      MRp\        V\        4      '       d   VP	                  R4      MRpVe   \        V4      ^ 8”  d   \        V4      # \        #   \         d	     \        # i ; i)ar  Read ``tool_budget.mcp_result_size_chars`` via ``load_config_readonly`` (the
sanctioned path; raw config.yaml parsing outside owner modules is test-guarded).
Any error, missing key or non-positive value returns the built-in default.

The ``tool_budget:`` block name is shared with the wider configurable-caps proposal (#80508) so the two
can merge without a key rename.
)Úload_config_readonlyÚtool_budgetNÚmcp_result_size_chars)Úhermes_cli.configr   Ú
isinstanceÚdictÚgetr   Ú	ExceptionÚDEFAULT_MCP_RESULT_SIZE_CHARS)r   ÚdataÚblockÚraws       r   Ú_configured_mcp_result_sizer      s†   € ðÝ:Ù#Ó%ˆÜ+5°d¼D×+AÒ+A�—‘˜Ô'ÀtˆÜ4>¸uÄd×4KÒ4Kˆe�i‰iÐ/Ô0ÐQUˆØŠ?œs 3›x¨!œ|Ü�s“8ˆOô )Ð(øô ô ØÜ(Ð(ðús   ‚A=B ÂBÂBT)Úfrozenc                   ód   a € ] tR t^-t o Rt]t]t]	t
]t]! ]R7      tV 3R lR ltV 3R ltRtV tR# )ÚBudgetConfigzšImmutable budget constants: per-result threshold (``resolve_threshold``),
per-turn aggregate (``turn_budget``) and inline snippet size (``preview_size``).)Údefault_factoryc                ó6   <€ V ^8„  d   QhRS[ RS[S[,          /# )r
   Ú	tool_namer   )Ústrr   Úfloat)r   Ú__classdict__s   "€r   r   ÚBudgetConfig.__annotate__8   s   ø€ ÷ =ñ =©3ð =±3¹µ;ñ =r   c                ó€  € V\         9   d   \         V,          # WP                  9   d   V P                  V,          # VP                  \        4      '       d!   \	        V P
                  V P                  4      # ^ RIHp VP                  WP                  R7      pV\        R4      8X  d   V# \	        W0P                  4      # )aü  Priority: pinned -> tool_overrides -> mcp_ prefix -> registry per-tool -> default.
MCP tools get ``mcp_result_size`` (no registry entry). MCP and registry values
are capped at ``default_result_size`` so a context-scaled budget for a small
model still constrains tools registering a fixed 100K ``max_result_size_chars``.

For the default budget this is a no-op because both equal 100K; for a scaled-down budget it prevents
a per-tool registry value from re-inflating the cap past the model's window (#23767).
)Úregistry)Údefaultr   )ÚPINNED_THRESHOLDSÚtool_overridesÚ
startswithÚMCP_TOOL_PREFIXÚminÚmcp_result_sizeÚdefault_result_sizeÚtools.registryr*   Úget_max_result_sizer&   )Úselfr$   r*   Úregistry_values   &&  r   Úresolve_thresholdÚBudgetConfig.resolve_threshold8   sž   € ð Ô)Ô)Ü$ YÕ/Ð/Ø×+Ñ+Ô+Ø×&Ñ& yÕ1Ð1Ø×Ñ¤×0Ò0Ü�t×+Ñ+¨T×-EÑ-EÓFÐFÝ+Ø!×5Ñ5°i×IaÑIaÐ5ÓbˆØœU 5›\Ô)Ø!Ð!Ü�>×#;Ñ#;Ó<Ð<r   c                ól   <€ V ^8„  d   Qh/ S[ ;R&   S[ ;R&   S[ ;R&   S[ ;R&   S[S[S[ 3,          ;R&   # )r
   r2   Úturn_budgetÚpreview_sizer1   r-   )r   r   r%   )r   r'   s   "€r   r   r(   -   sN   ø‡ ‚ ñ
 Ñ8ñ ñ Ñ0ñ ñ Ñ2ñ ñ Ñ8ñ ñ ™™c˜•NÑ@ò r   © N)Ú__name__Ú
__module__Ú__qualname__Ú__firstlineno__Ú__doc__ÚDEFAULT_RESULT_SIZE_CHARSr2   ÚDEFAULT_TURN_BUDGET_CHARSr:   ÚDEFAULT_PREVIEW_SIZE_CHARSr;   r   r1   r   r   r-   r7   Ú__annotate_func__Ú__static_attributes__Ú__classdictcell__)r'   s   @r   r!   r!   -   s=   ø‡ € ñXð  9ÐØ0€KØ2€LØ8€OÙ%*¸4Ô%@€N÷=ð =÷ ƒ r   r!   g333333Ã?g333333Ó?i@  i€>  c                ó>   € V ^8„  d   QhR\         R,          R\        /# )r
   Úcontext_lengthNr   )r   r!   )r   s   "r   r   r   \   s   € ÷ ñ ¬c°D­jð ¼\ñ r   c                ón  € \        4       pV '       d   V ^ 8:  d   V\        8X  d   \        # \        VR7      # V \        ,          p\        \        \        \        \        V\        ,          4      \        4      4      \        \        \        \        V\        ,          4      \        4      4      \        VR7      # )am  Return a BudgetConfig scaled to the model's context window: the fixed
defaults suit 200K+ models but on 65K one result/turn can fill the window.
The proportional value is clamped to the defaults as a CAP (large models
stay byte-identical) and floored so a usable preview always survives.

The fixed defaults (100K result / 200K turn chars) are correct for large (200K+ token) models but blind
to small ones: on a 65K-token model a single tool result persisted at the 100K-char threshold, or a
200K-char turn budget (~50K tokens), can by itself approach or exceed the whole window and force an
oversized request (#23767).
)r1   )r2   r:   r;   r1   )r   r   ÚDEFAULT_BUDGETr!   Ú_CHARS_PER_TOKENÚmaxÚ_MIN_RESULT_SIZE_CHARSr0   r   Ú_PER_RESULT_WINDOW_FRACTIONrB   Ú_MIN_TURN_BUDGET_CHARSÚ_PER_TURN_WINDOW_FRACTIONrC   rD   )rI   r1   Úwindow_charss   &  r   Úbudget_for_context_windowrS   \   s”   € ô 2Ó3€Oß˜^¨qÔ0ØÔ;Ô;Ü!Ð!Ü¨OÔ<Ð<Ø!Ô$4Õ4€LÜÜÔ 6¼¼CÀÔOjÕ@jÓ<kô  nGó  9Hó  IÜÔ.´´C¸ÔG`Õ8`Ó4aÔc|Ó0}Ó~Ü/Ø'ô	ð r   c                óò  € V ^8„  d   Qh/ ^ \         9   d   \        \        \        3,          ;R&   ^\         9   d
   \        ;R&   ^\         9   d
   \        ;R&   ^\         9   d
   \        ;R&   ^\         9   d
   \        ;R&   ^\         9   d
   \        ;R&   ^\         9   d
   \        ;R&   ^\         9   d
   \        ;R&   ^\         9   d
   \        ;R	&   ^	\         9   d
   \        ;R
&   ^
\         9   d
   \        ;R&   # )r
   r,   rB   rC   rD   r   r/   rL   rO   rQ   rN   rP   )Ú__conditional_annotations__r   r%   r&   r   )r   s   "r   r   r      só   € ÷ Hñ H÷ BÒ A”4œœU˜
Õ#Ñ AñH÷ )Ò (œ3Ñ (ñH÷ )Ò (œ3Ñ (ñH÷ (Ò 'œCÑ 'ñH÷& ,Ò +œsÑ +ñ'H÷* Ò ”Ñ ñ+H÷b (Ò '”#Ñ 'ñcH÷h *Ò )œUÑ )ñiH÷j (Ò 'œ5Ñ 'ñkH÷n $Ò #œÑ #ñoH÷p %Ò $œÑ $òqHr   N)rU   rA   Údataclassesr   r   Útypingr   Úagent.model_metadatar   r&   r,   rB   rC   rD   r   r/   r   r!   rK   rL   rO   rQ   rN   rP   rS   r   )rU   s   @r   Ú<module>rY      s¾   øðöH÷ )Ý å 0ð (3±E¸%³LÐ&AÐ Ó Að ")Ð Ó (Ø!(Ð Ó (Ø"'Ð Ó 'ð
 &,Ð Ó +à€Ó õ)ñ( �$Ô÷=ð =ó ð=ñB “€ð (Ð Ó 'ð &*Ð Ó )Ø#'Ð Ó 'à#Ð Ó #Ø$Ð Ó $÷r   