shin / tests /application /test_reasoning.py
LastNoob's picture
Honor reasoning tiers on numeric-budget providers (#1150)
4faabdf unverified
Raw
History Blame Contribute Delete
4.97 kB
import pytest
from free_claude_code.application.reasoning import (
client_reasoning_policy,
resolve_reasoning_policy,
)
from free_claude_code.config.reasoning import ReasoningPreference
from free_claude_code.core.anthropic.models import MessagesRequest
from free_claude_code.core.reasoning import (
ReasoningControl,
ReasoningEffort,
ReasoningPolicy,
)
def _request(**overrides) -> MessagesRequest:
payload = {
"model": "provider/model",
"messages": [{"role": "user", "content": "hello"}],
}
payload.update(overrides)
return MessagesRequest.model_validate(payload)
def test_client_without_reasoning_control_uses_provider_default() -> None:
assert client_reasoning_policy(_request()) == ReasoningPolicy.provider_default()
def test_client_reasoning_preserves_effort_and_exact_budget() -> None:
policy = client_reasoning_policy(
_request(
thinking={"type": "enabled", "budget_tokens": 4096},
output_config={"effort": "xhigh"},
)
)
assert policy == ReasoningPolicy.on(
effort=ReasoningEffort.XHIGH,
budget_tokens=4096,
)
def test_named_effort_preserves_intent_without_exact_client_budget() -> None:
policy = client_reasoning_policy(_request(output_config={"effort": "high"}))
assert policy == ReasoningPolicy(
control=ReasoningControl.DEFAULT,
effort=ReasoningEffort.HIGH,
)
assert policy.budget_tokens is None
assert policy.requests_reasoning is True
def test_invalid_budget_does_not_implicitly_enable_reasoning() -> None:
policy = client_reasoning_policy(_request(thinking={"budget_tokens": 0}))
assert policy == ReasoningPolicy.provider_default()
@pytest.mark.parametrize(
"messages_request",
[
_request(thinking={"type": "disabled"}),
_request(output_config={"effort": "none"}),
],
)
def test_client_disable_is_explicit(messages_request: MessagesRequest) -> None:
policy = client_reasoning_policy(messages_request)
assert policy.control is ReasoningControl.OFF
assert policy.output_enabled is False
assert policy.requests_reasoning is False
def test_disabled_thinking_preserves_independent_effort_intent() -> None:
policy = client_reasoning_policy(
_request(
thinking={"type": "disabled"},
output_config={"effort": "medium"},
)
)
assert policy == ReasoningPolicy(
control=ReasoningControl.OFF,
effort=ReasoningEffort.MEDIUM,
)
assert policy.requests_reasoning is False
def test_fixed_route_effort_overrides_client_disable() -> None:
policy = resolve_reasoning_policy(
_request(thinking={"type": "disabled"}),
ReasoningPreference.MAX,
)
assert policy == ReasoningPolicy.on(effort=ReasoningEffort.MAX)
def test_fixed_off_overrides_client_enable() -> None:
policy = resolve_reasoning_policy(
_request(thinking={"type": "enabled", "budget_tokens": 1024}),
ReasoningPreference.OFF,
)
assert policy == ReasoningPolicy.off()
def test_client_preference_preserves_client_policy() -> None:
request = _request(output_config={"effort": "low"})
assert resolve_reasoning_policy(
request, ReasoningPreference.CLIENT
) == client_reasoning_policy(request)
def test_unresolved_inherit_is_rejected() -> None:
with pytest.raises(ValueError, match="must be resolved"):
resolve_reasoning_policy(_request(), ReasoningPreference.INHERIT)
@pytest.mark.parametrize("budget", [0, -1, True])
def test_reasoning_budget_requires_a_positive_integer(budget: int) -> None:
with pytest.raises(ValueError, match="positive integer"):
ReasoningPolicy.on(budget_tokens=budget)
def test_reasoning_budget_requires_explicit_on_control() -> None:
with pytest.raises(ValueError, match="control to be on"):
ReasoningPolicy(budget_tokens=100)
@pytest.mark.parametrize(
("effort", "expected"),
(
(ReasoningEffort.MINIMAL, 512),
(ReasoningEffort.LOW, 512),
(ReasoningEffort.MEDIUM, 1_024),
(ReasoningEffort.HIGH, 2_048),
(ReasoningEffort.XHIGH, 4_096),
(ReasoningEffort.MAX, 8_192),
),
)
def test_reasoning_effort_has_one_fcc_numeric_budget(
effort: ReasoningEffort, expected: int
) -> None:
assert ReasoningPolicy.on(effort=effort).numeric_budget_tokens == expected
def test_exact_reasoning_budget_takes_precedence_over_effort_mapping() -> None:
policy = ReasoningPolicy.on(
effort=ReasoningEffort.XHIGH,
budget_tokens=777,
)
assert policy.numeric_budget_tokens == 777
@pytest.mark.parametrize(
"policy",
(
ReasoningPolicy.provider_default(),
ReasoningPolicy.off(),
ReasoningPolicy.on(),
),
)
def test_reasoning_without_numeric_intensity_has_no_budget(
policy: ReasoningPolicy,
) -> None:
assert policy.numeric_budget_tokens is None