fix: normalize DashScope reasoning_effort (minimal vs minimum)
DashScope rejects the OpenAI-style value "minimal" with `'reasoning_effort.effort' must be one of: 'none', 'minimum', 'low', 'medium', 'high', 'xhigh'`, but nanobot was passing the string through verbatim. Users who tried the documented "minimal" to disable thinking got a 400; users who tried the DashScope-native "minimum" to work around it got `enable_thinking=True` because the internal comparison was a hard string match on "minimal". Introduce a semantic/wire split in `_build_kwargs`: - `semantic_effort` is the internal canonical form (OpenAI vocabulary). "minimum" on the way in is normalized to "minimal" here so both spellings share one meaning. - `wire_effort` is what we actually serialize. For DashScope with semantic_effort == "minimal" we translate to "minimum" on the way out; other providers are unchanged. - `thinking_enabled` and the Kimi thinking branch now compare on `semantic_effort`, so either user spelling correctly disables provider-side thinking. Tests: - Strengthen `test_dashscope_thinking_disabled_for_minimal` to assert the wire value is "minimum" in addition to the extra_body signal; the original version only checked extra_body and let the invalid-value bug slip through. - Add `test_dashscope_thinking_disabled_for_minimum_alias` so a user who read the DashScope docs and configured "minimum" still gets thinking off. - Add `test_non_dashscope_minimal_not_retranslated` to pin down that the DashScope-specific translation does not leak to OpenAI et al.
This commit is contained in:
@@ -731,10 +731,32 @@ def test_dashscope_thinking_enabled_with_reasoning_effort() -> None:
|
||||
|
||||
|
||||
def test_dashscope_thinking_disabled_for_minimal() -> None:
|
||||
"""OpenAI-style 'minimal' → DashScope wire value 'minimum' + thinking off.
|
||||
DashScope rejects the literal string 'minimal' (invalid_value), so we
|
||||
must translate on the outbound side while still honouring the 'no
|
||||
thinking' intent via extra_body."""
|
||||
kw = _build_kwargs_for("dashscope", "qwen3-plus", reasoning_effort="minimal")
|
||||
assert kw["reasoning_effort"] == "minimum"
|
||||
assert kw["extra_body"] == {"enable_thinking": False}
|
||||
|
||||
|
||||
def test_dashscope_thinking_disabled_for_minimum_alias() -> None:
|
||||
"""Users who read DashScope docs may configure the native 'minimum'
|
||||
spelling. Internally it's the same semantic as 'minimal' → thinking
|
||||
must still be disabled (not enabled just because the string isn't
|
||||
literally 'minimal')."""
|
||||
kw = _build_kwargs_for("dashscope", "qwen3-plus", reasoning_effort="minimum")
|
||||
assert kw["reasoning_effort"] == "minimum"
|
||||
assert kw["extra_body"] == {"enable_thinking": False}
|
||||
|
||||
|
||||
def test_non_dashscope_minimal_not_retranslated() -> None:
|
||||
"""The DashScope-specific translation must not leak to other providers;
|
||||
OpenAI / Anthropic / etc. speak 'minimal' natively."""
|
||||
kw = _build_kwargs_for("openai", "gpt-5", reasoning_effort="minimal")
|
||||
assert kw["reasoning_effort"] == "minimal"
|
||||
|
||||
|
||||
def test_dashscope_no_extra_body_when_reasoning_effort_none() -> None:
|
||||
kw = _build_kwargs_for("dashscope", "qwen-turbo", reasoning_effort=None)
|
||||
assert "extra_body" not in kw
|
||||
|
||||
Reference in New Issue
Block a user