Skip to content

fix(providers): wire MiMo thinking control on gateway providers (#3845) - #3851

Merged
Re-bin merged 1 commit into
HKUDS:mainfrom
olgagaga:fix/mimo-thinking-gateway
May 16, 2026
Merged

Re-bin merged 1 commit into
HKUDS:mainfrom
olgagaga:fix/mimo-thinking-gateway

Conversation

@olgagaga

Copy link
Copy Markdown
Contributor

Summary

Why an explicit allowlist (not a substring rule)

It matches Kimi's approach, keeps mimo-v2-flash out without special-casing, and the canonical model list was already enumerated in the existing test docstring — no new policy decision needed.

Test plan

  • pytest tests/providers/test_xiaomi_mimo_thinking.py -v — 11 passed (6 existing + 5 new)
  • pytest tests/providers/ -q — 408 passed, no regressions in adjacent paths (Kimi, DeepSeek, DashScope)
  • ruff check nanobot/providers/openai_compat_provider.py tests/providers/test_xiaomi_mimo_thinking.py — clean
  • New tests cover: OpenRouter disable signal, OpenRouter enable signal, bare-slug fallback, mimo-v2-flash exclusion, non-MiMo non-Kimi sanity

Notes for reviewers

  • Two branches now overlap for direct xiaomi_mimo requests of allowlisted models (spec-driven + model-name). They write the same payload, so the dict update is an idempotent no-op — no behavior change on the direct path.
  • The fix is intentionally scoped to the issue. The latent question of whether the spec-driven branch should also gate on _is_mimo_thinking_model (currently it injects for mimo-v2-flash too) is left as a follow-up if desired.

…S#3845)

The xiaomi_mimo ProviderSpec carries thinking_style="thinking_type", but
gateway providers (OpenRouter etc.) route MiMo under their own spec
which has no thinking_style. As a result, `reasoning_effort="none"` was
silently ignored: `{"thinking": {"type": "disabled"}}` was never
injected and responses still contained reasoning_content.

Mirror the Kimi pattern that already handles the same problem: add an
explicit _MIMO_THINKING_MODELS allowlist (mimo-v2.5-pro, mimo-v2.5,
mimo-v2-pro, mimo-v2-omni — per Xiaomi docs), an _is_mimo_thinking_model
helper that strips publisher prefixes ("xiaomi/mimo-v2.5-pro" matches),
and a sibling branch in _build_kwargs that injects the thinking payload
by model name. mimo-v2-flash is intentionally excluded — it has no
thinking mode.

Also include MiMo in the explicit_thinking predicate so the
reasoning_content backfill (HKUDS#3554, HKUDS#3584) covers the gateway path
consistently with the direct path.

Tests cover the gateway disable/enable signals, bare-slug fallback,
flash exclusion, and a non-MiMo sanity check.
@Re-bin
Re-bin merged commit 0ca0fe2 into HKUDS:main May 16, 2026
2 checks passed
@ClearPlume

Copy link
Copy Markdown

@chengyongru @olgagaga

I don't know why... It seems the logic to disable thinking is in effect, and kwargs has been updated correctly, but the model still thinks when using Openrouter.

I don't have time to delve deeper into the nanobot code right now, but I have a vague guess—is there a similar situation requiring _is_mimo_thinking_model in the processing logic related to extra_body?

fallingangel@fallingangel-vps~nanob.txt

The vim command between the two runs was switching the provider from openrouter to xiaomiMimo — everything else stayed the same.

@olgagaga

olgagaga commented May 16, 2026 •

Copy link
Copy Markdown
Contributor Author

@ClearPlume Thanks, you are right: extra_body.thinking is MiMo's upstream shape and OpenRouter strips it and uses its own reasoning field, so the disable signal never reached the model.

Follow-up in #3867, it also injects extra_body.reasoning = {effort: "none"} (by OR documentation) when routing Kimi/MiMo through OR. Both fields go out so direct paths unchanged, OR now honors the setting. Would appreciate a verification against your setup once it's merged.

Re-bin pushed a commit that referenced this pull request May 21, 2026
Follow-up to #3851: that PR added `extra_body.thinking={type: disabled}`
for MiMo via OpenRouter, but OR doesn't forward provider-specific
thinking shapes to upstream — it strips unknown extra_body fields and
uses its own unified `reasoning` parameter. So MiMo via OR kept
thinking despite the injection (reproduced by @ClearPlume on #3851
with identical kwargs but provider switched from openrouter → xiaomi_mimo).

For known thinking-capable models (Kimi, MiMo) routed via the
openrouter spec, also inject `extra_body.reasoning = {effort: <effort>}`
in OR's documented enum ("none"|"minimal"|"low"|"medium"|"high"|"xhigh").
OR translates this to the upstream model's native shape.

Existing tests updated to expect both fields on the OR path. The direct
xiaomi_mimo and moonshot paths are unchanged (the new branch is gated
on spec.name == "openrouter"). Flash and non-MiMo models on OR continue
to receive no injection.
Erlichooo pushed a commit to Erlichooo/nanobot that referenced this pull request May 23, 2026
Follow-up to HKUDS#3851: that PR added `extra_body.thinking={type: disabled}`
for MiMo via OpenRouter, but OR doesn't forward provider-specific
thinking shapes to upstream — it strips unknown extra_body fields and
uses its own unified `reasoning` parameter. So MiMo via OR kept
thinking despite the injection (reproduced by @ClearPlume on HKUDS#3851
with identical kwargs but provider switched from openrouter → xiaomi_mimo).

For known thinking-capable models (Kimi, MiMo) routed via the
openrouter spec, also inject `extra_body.reasoning = {effort: <effort>}`
in OR's documented enum ("none"|"minimal"|"low"|"medium"|"high"|"xhigh").
OR translates this to the upstream model's native shape.

Existing tests updated to expect both fields on the OR path. The direct
xiaomi_mimo and moonshot paths are unchanged (the new branch is gated
on spec.name == "openrouter"). Flash and non-MiMo models on OR continue
to receive no injection.
@olgagaga
olgagaga deleted the fix/mimo-thinking-gateway branch May 25, 2026 16:50
StefanoParadisi pushed a commit to StefanoHernandez/nanobot that referenced this pull request Oct 16, 2026
Follow-up to HKUDS#3851: that PR added `extra_body.thinking={type: disabled}`
for MiMo via OpenRouter, but OR doesn't forward provider-specific
thinking shapes to upstream — it strips unknown extra_body fields and
uses its own unified `reasoning` parameter. So MiMo via OR kept
thinking despite the injection (reproduced by @ClearPlume on HKUDS#3851
with identical kwargs but provider switched from openrouter → xiaomi_mimo).

For known thinking-capable models (Kimi, MiMo) routed via the
openrouter spec, also inject `extra_body.reasoning = {effort: <effort>}`
in OR's documented enum ("none"|"minimal"|"low"|"medium"|"high"|"xhigh").
OR translates this to the upstream model's native shape.

Existing tests updated to expect both fields on the OR path. The direct
xiaomi_mimo and moonshot paths are unchanged (the new branch is gated
on spec.name == "openrouter"). Flash and non-MiMo models on OR continue
to receive no injection.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[BUG] MiMo thinking control not working through gateway providers (OpenRouter)

4 participants