Skip to content

fix(agent): preserve reasoning_content on Xiaomi MiMo thinking endpoints#24737

Open
xx9090950 wants to merge 1 commit into
NousResearch:mainfrom
xx9090950:fix/xiaomi-anthropic-thinking-reasoning-content
Open

fix(agent): preserve reasoning_content on Xiaomi MiMo thinking endpoints#24737
xx9090950 wants to merge 1 commit into
NousResearch:mainfrom
xx9090950:fix/xiaomi-anthropic-thinking-reasoning-content

Conversation

@xx9090950

Copy link
Copy Markdown

What does this PR do?

Xiaomi MiMo (mimo-v2.5-pro, mimo-v2.5, …) is a DeepSeek-derived thinking-capable model family. Both its OpenAI-compatible api.xiaomimimo.com/v1 endpoint and its Anthropic-compatible token-plan-*.xiaomimimo.com/anthropic endpoint enforce the same reasoning_content echo-back contract as DeepSeek and Kimi: when a persisted session replays an assistant tool-call turn that was recorded without reasoning_content, Xiaomi rejects the next request with HTTP 400:

The reasoning_content in the thinking mode must be passed back to the API.

But the existing guards only matched DeepSeek and Kimi:

  • _preserve_unsigned_thinking (agent/anthropic_adapter.py) drops reasoning_content-derived thinking blocks for any non-whitelisted third-party /anthropic endpoint, so Xiaomi history loses its thinking blocks on replay.
  • _needs_thinking_reasoning_pad (run_agent.py) doesn't pad/preserve reasoning_content on tool-call turns for Xiaomi, so even new turns are persisted without the field.

This PR adds Xiaomi to both whitelists, mirroring the DeepSeek policy verbatim. Same strip-signed / keep-unsigned policy, same three detection signals, same regression test layout — Xiaomi-shaped scenarios were just missing from the whitelist.

Related Issue

Fixes an unfiled bug; reproduction is straightforward (see How to Test). Happy to file a tracking issue if maintainers prefer one.

Type of Change

  • 🐛 Bug fix (non-breaking change that fixes an issue)
  • ✨ New feature (non-breaking change that adds functionality)
  • 🔒 Security fix
  • 📝 Documentation update
  • ✅ Tests (adding or improving test coverage)
  • ♻️ Refactor (no behavior change)
  • 🎯 New skill (bundled or hub)

Changes Made

  • agent/anthropic_adapter.py
    • Add _is_xiaomi_anthropic_endpoint(base_url) — pinned to the /anthropic path (host match xiaomimimo.com covers token-plan-{cn,sgp,ams,…} regional subdomains). The OpenAI-compatible /v1 base URL never reaches this adapter, so detection fails closed there.
    • Add _is_xiaomi_anthropic_endpoint(base_url) to the _preserve_unsigned_thinking whitelist in convert_messages_to_anthropic, alongside _is_kimi_family_endpoint and _is_deepseek_anthropic_endpoint.
  • run_agent.py
    • Add _needs_xiaomi_tool_reasoning() — three detection signals matching the DeepSeek shape: provider == "xiaomi", model starts with mimo-, or host matches xiaomimimo.com (covers both /v1 and /anthropic transports).
    • Wire it into _needs_thinking_reasoning_pad().
  • tests/agent/test_xiaomi_anthropic_thinking.py — new: unsigned thinking block survival on /anthropic, signed-block stripping, OpenAI-base fail-closed, substring false-positive guard. (10 tests)
  • tests/run_agent/test_xiaomi_reasoning_content_echo.py — new: detection signals, replay padding, build-time pinning, cross-provider history guard, parametrized pad scenarios. (22 tests)

How to Test

Reproduce the bug (before this fix)

# cli-config.yaml
model:
  default: mimo-v2.5-pro
  provider: xiaomi
  base_url: https://token-plan-cn.xiaomimimo.com/anthropic
  api_mode: anthropic_messages

Run any multi-turn session that uses terminal or another tool (a cron job that fetches a URL is a good reproducer). On the second tool-call turn, the upstream call fails with:

RuntimeError: Error code: 400 - {'error': {'code': '400', 'message': 'Param Incorrect',
  'param': 'The reasoning_content in the thinking mode must be passed back to the API.',
  'type': ''}}

Verify the fix

  1. pytest tests/agent/test_xiaomi_anthropic_thinking.py tests/run_agent/test_xiaomi_reasoning_content_echo.py -q — 32 new tests pass.
  2. pytest tests/run_agent/test_deepseek_reasoning_content_echo.py tests/agent/test_deepseek_anthropic_thinking.py tests/agent/test_kimi_coding_anthropic_thinking.py tests/hermes_cli/test_xiaomi_provider.py -q — 114 existing tests still pass (no regression on DeepSeek / Kimi / xiaomi provider).
  3. Rerun the cron job / multi-turn session against token-plan-cn.xiaomimimo.com/anthropic — the next tool-call turn now carries the synthesised thinking block on replay and the 400 disappears.

Checklist

Code

  • I've read the Contributing Guide
  • My commit messages follow Conventional Commits (fix(agent): …)
  • I searched for existing PRs to make sure this isn't a duplicate
  • My PR contains only changes related to this fix (no unrelated commits)
  • I've run the relevant test suites locally — see How to Test above (1462 tests pass; two pre-existing failures on maintest_switch_model_preserves_config_context_length and test_interrupt_child_during_api_call — are unrelated to this change and reproduce on a clean checkout)
  • I've added tests for my changes — 32 new tests covering both the detection helpers and the conversion path
  • I've tested on my platform: macOS 15 (Darwin 25.2.0), Python 3.11.14

Documentation & Housekeeping

  • I've updated relevant documentation — docstrings on the new helpers explain the contract; no user-facing docs needed
  • I've updated cli-config.yaml.example if I added/changed config keys — N/A (no new config keys)
  • I've updated CONTRIBUTING.md or AGENTS.md if I changed architecture or workflows — N/A (no architectural change)
  • I've considered cross-platform impact — change is pure Python string/dict handling; no I/O, no platform-specific code
  • I've updated tool descriptions/schemas if I changed tool behavior — N/A (tool surface unchanged)

Xiaomi MiMo (mimo-v2.5-pro, mimo-v2.5, ...) is a DeepSeek-derived
thinking-capable model family. Both its OpenAI-compatible
``api.xiaomimimo.com/v1`` endpoint and its Anthropic-compatible
``token-plan-*.xiaomimimo.com/anthropic`` endpoint enforce the same
reasoning_content echo-back contract as DeepSeek and Kimi: when a
persisted session replays an assistant tool-call turn that was recorded
without reasoning_content, Xiaomi rejects the next request with HTTP
400::

    The reasoning_content in the thinking mode must be passed back
    to the API.

But the existing guards only matched DeepSeek and Kimi:

- ``_preserve_unsigned_thinking`` (agent/anthropic_adapter.py) — drops
  reasoning_content-derived thinking blocks for any non-whitelisted
  third-party /anthropic endpoint, so Xiaomi history loses its thinking
  blocks on replay.
- ``_needs_thinking_reasoning_pad`` (run_agent.py) — doesn't pad/preserve
  reasoning_content on tool-call turns for Xiaomi, so even new turns
  are persisted without the field.

Add Xiaomi to both whitelists, mirroring the DeepSeek policy:

- ``_is_xiaomi_anthropic_endpoint`` — pinned to the ``/anthropic`` path
  (host match ``xiaomimimo.com`` covers ``token-plan-{cn,sgp,ams,...}``
  regional subdomains). The OpenAI-compatible ``/v1`` base URL never
  reaches this adapter, so detection fails closed there.
- ``_needs_xiaomi_tool_reasoning`` — three detection signals matching
  the DeepSeek shape: ``provider == "xiaomi"``, model starts with
  ``mimo-``, or host matches ``xiaomimimo.com`` (covers both /v1 and
  /anthropic transports).

Coverage:

- ``tests/agent/test_xiaomi_anthropic_thinking.py`` — unsigned thinking
  block survival, signed-block stripping, OpenAI-base fail-closed,
  substring false-positive guard.
- ``tests/run_agent/test_xiaomi_reasoning_content_echo.py`` — detection
  signals, replay padding, build-time pinning, cross-provider history
  guard, parametrized pad scenarios.

Tested on macOS Darwin 25.2.0, Python 3.11.14; 32 new tests pass,
existing DeepSeek/Kimi/xiaomi-provider suites (82 tests) unchanged.
@alt-glitch alt-glitch added type/bug Something isn't working P3 Low — cosmetic, nice to have comp/agent Core agent loop, run_agent.py, prompt builder provider/xiaomi Xiaomi MiLM labels May 13, 2026
@alt-glitch

Copy link
Copy Markdown
Collaborator

Duplicate of #24465 (earliest open PR for Xiaomi MiMo reasoning_content replay support). Also competes with #24603, #24605, #24726, #24747.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comp/agent Core agent loop, run_agent.py, prompt builder P3 Low — cosmetic, nice to have provider/xiaomi Xiaomi MiLM type/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants