fn read_reasoning_budget_tokens(
obj: &Map<String, Value>,
issues: &mut Vec<FieldIssue>,
) -> Option<i32>Expand description
Read the reasoning_budget_tokens field, under either name upstream
accepts for it.
Exactly upstream’s range and nothing narrower: -1 <= v <= i32::MAX, with
-1 meaning “defer to the launch --reasoning-budget” and 0 meaning
“stop thinking immediately”. llama-server answers -2 with an HTTP 400
naming that range, so rejecting below -1 here reproduces upstream’s own
verdict rather than adding a gglib opinion — the difference from
read_reasoning_effort, which has no upstream verdict to reproduce.
§The alias is read, and the canonical key wins
llama-server accepts THINKING_BUDGET_TOKENS_KEY as a second spelling of
the same parameter (ADR 0007 finding 7c). A reader that knew only the
canonical name left the alias ungoverned: it entered no layer, appeared in
no discard record, was overwritten by no force-insert, and so an untrusted
client’s thinking_budget_tokens outranked the operator’s resolved budget
silently — the #779 shape this arc exists to close.
Whichever name arrives, the value becomes
InferenceConfig::reasoning_budget_tokens and is governed like any other
client-authoritative budget. With both present the canonical key wins,
because that is the name gglib itself emits and the one every other surface
(provenance, the audit, gglib model explain) reports. An explicit null
counts as absent under either name, as it does for every other reader here.
Issues are reported against the key the client actually sent, so a refusal names the text that was in the request rather than a name the client never used.