Skip to content

feat: add Xiaomi MiMo provider support#2240

Open
HUQIANTAO wants to merge 10 commits into
Hmbown:mainfrom
HUQIANTAO:feat/xiaomi-mimo-support
Open

feat: add Xiaomi MiMo provider support#2240
HUQIANTAO wants to merge 10 commits into
Hmbown:mainfrom
HUQIANTAO:feat/xiaomi-mimo-support

Conversation

@HUQIANTAO
Copy link
Copy Markdown

@HUQIANTAO HUQIANTAO commented May 27, 2026

Summary

  • Add first-class Xiaomi MiMo provider support with dedicated API integration via token-plan endpoint (https://token-plan-cn.xiaomimimo.com/v1)
  • Support two MiMo models: mimo-v2.5-pro (reasoning flagship) and mimo-v2.5 (omni)
  • Implement MiMo-specific thinking toggle (thinking: { type: "enabled"/"disabled" }) instead of DeepSeek-style reasoning_effort
  • Enable /models command for Xiaomi provider to fetch available models from the API
  • Add provider-specific model picker UI with MiMo models and simplified thinking effort (off/high)

Changes

Provider registration:

  • crates/config/src/lib.rsProviderKind::Xiaomi variant, default model/base_url constants, parse/as_str
  • crates/tui/src/config.rsApiProvider::Xiaomi variant, provider_capability (thinking enabled), all match arms
  • crates/cli/src/lib.rsProviderArg::Xiaomi, provider list, env var mapping

Model picker & validation:

  • crates/tui/src/tui/model_picker.rs — Provider-specific model lists (PICKER_MODELS_XIAOMI) and thinking effort lists (PICKER_EFFORTS_MIMO with only off/high)
  • crates/tui/src/config.rsnormalize_model_name_for_provider accepts MiMo model names for Xiaomi provider

API integration:

  • crates/tui/src/client.rsapply_reasoning_effort sends thinking: { type: "disabled" } for off, thinking: { type: "enabled" } for high/max
  • crates/tui/src/client/chat.rsrequires_reasoning_content() includes mimo prefix for reasoning token replay
  • crates/tui/src/tui/ui.rs — Allow /models command for Xiaomi provider

Model registry:

  • crates/agent/src/lib.rsModelInfo entries for mimo-v2.5-pro and mimo-v2.5 with aliases

Config & docs:

  • config.example.toml[providers.xiaomi] section with token-plan URL and model examples
  • .env.exampleMIMO_API_KEY, MIMO_BASE_URL, MIMO_MODEL documentation

Test plan

  • cargo fmt --all -- --check passes
  • cargo clippy --workspace --all-targets --all-features --locked -- -D warnings passes
  • cargo test --workspace --all-features --locked passes (4 pre-existing failures unrelated to this change)
  • Manual TUI test: /provider → Xiaomi MiMo, /model → mimo-v2.5-pro, send a message
  • Manual TUI test: /model → switch thinking effort off/high, verify API accepts the request
  • Manual TUI test: /models → verify model list is fetched from Xiaomi API
  • Manual TUI test: restart app → verify Xiaomi provider and MiMo model are persisted

Greptile Summary

This PR adds first-class Xiaomi MiMo provider support, wiring ProviderKind::Xiaomi / ApiProvider::Xiaomi through every layer of the stack — config, secrets, CLI, TUI engine, model picker, reasoning-effort translation, and reasoning-content replay. The implementation is comprehensive and follows the existing provider-addition pattern faithfully.

  • API integration: apply_reasoning_effort maps MiMo's thinking: { type: \"enabled\"/\"disabled\" } format (no reasoning_effort field) across all effort levels; requires_reasoning_content and provider_accepts_reasoning_content are extended so multi-turn tool-call reasoning content is replayed correctly per MiMo docs.
  • Model picker refactor: The hide_deepseek_models boolean is replaced with provider-specific provider_models/provider_efforts slices; Xiaomi gets PICKER_MODELS_XIAOMI (auto, mimo-v2.5-pro, mimo-v2.5) and a two-item effort list (off/high).
  • /models support: Xiaomi is allowed to fetch available models despite living inside provider_passes_model_through, achieved via a && !is_xiaomi carve-out in the FetchModels gate.

Confidence Score: 5/5

Safe to merge — all Xiaomi variant arms are exhaustive (Rust compile-time enforcement), the reasoning-content replay path is consistent with existing providers, and manual end-to-end testing is confirmed in the test plan.

The change is a well-scoped provider addition that follows the existing pattern exactly. Every match arm across config, secrets, CLI, TUI, and model picker is complete. The reasoning-effort translation correctly maps MiMo's thinking toggle across all effort levels. The only non-trivial design choice — placing Xiaomi in provider_passes_model_through while also supporting /models — is functional and safe, if slightly surprising to future readers.

crates/tui/src/tui/ui.rs — the FetchModels guard uses a double-negative carve-out for Xiaomi that should be understood by anyone refactoring provider_passes_model_through in the future.

Important Files Changed

Filename Overview
crates/tui/src/client.rs Adds Xiaomi MiMo to all three effort branches (off/high/max) of apply_reasoning_effort; the low/medium branch correctly maps MiMo to thinking-enabled too. One misleading comment.
crates/tui/src/client/chat.rs Adds mimo prefix to requires_reasoning_content and Xiaomi to provider_accepts_reasoning_content; reasoning-content replay for multi-turn tool calls is consistent and correct.
crates/tui/src/config.rs Thorough Xiaomi variant wiring across provider_capability, model_completion_names, normalize_model_name_for_provider, env-override path, and all match arms; no missing cases detected.
crates/tui/src/tui/model_picker.rs Replaces hide_deepseek_models boolean with provider_models/provider_efforts slices; pass-through providers get an [auto] row, Xiaomi gets PICKER_MODELS_XIAOMI and PICKER_EFFORTS_MIMO (off/high only).
crates/tui/src/tui/ui.rs Adds Xiaomi to /models support and render provider tag; the FetchModels guard uses a double-negative because Xiaomi is both in provider_passes_model_through and also allowed to call /models — logically correct but fragile.
crates/config/src/lib.rs Adds Xiaomi variant with DEFAULT_XIAOMI_MODEL/BASE_URL, all match arms, TOML read/write/unset/list coverage, and env-var guard/restore in tests; comprehensive and consistent.
crates/agent/src/lib.rs Registers mimo-v2.5-pro and mimo-v2.5 with supports_reasoning: true and provider: Xiaomi; aliases are consistent with config.
crates/cli/src/lib.rs Adds ProviderArg::Xiaomi, PROVIDER_LIST entry, provider_slot, provider_env_vars (MIMO_API_KEY), and TUI guard for Xiaomi; all arms exhaustive.
crates/secrets/src/lib.rs Maps xiaomi/mimo/xiaomi-mimo slug to MIMO_API_KEY; consistent with all other provider key lookups.

Sequence Diagram

sequenceDiagram
    participant User
    participant TUI
    participant Config
    participant Client
    participant MiMoAPI

    User->>TUI: /provider → Xiaomi, /model → mimo-v2.5-pro
    TUI->>Config: "api_provider() == Xiaomi"
    Config-->>TUI: DEFAULT_XIAOMI_BASE_URL, MIMO_API_KEY

    User->>TUI: "Send message (effort = high)"
    TUI->>Client: apply_reasoning_effort(body, high, Xiaomi)
    Client->>Client: "body[thinking] = {type:enabled}"
    Note over Client: No reasoning_effort field (MiMo-specific)

    TUI->>Client: build_chat_request(messages)
    Client->>Client: requires_reasoning_content(mimo-v2.5-pro) → true
    Client->>Client: "should_replay_reasoning_content → replay if effort != off"

    Client->>MiMoAPI: POST /v1/chat/completions
    Note over Client,MiMoAPI: Bearer MIMO_API_KEY
    MiMoAPI-->>Client: SSE stream with reasoning_content + content
    Client-->>TUI: parsed MessageResponse
    TUI-->>User: display thinking + answer
Loading

Fix All in Codex Fix All in Claude Code Fix All in Cursor

Reviews (4): Last reviewed commit: "chore: bump version to 0.8.47 (dev)" | Re-trigger Greptile

Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request adds support for the Xiaomi MiMo Token Plan provider, integrating its models (mimo-v2.5-pro, mimo-v2.5, and mimo-v2-flash) into the configuration, CLI, and interactive TUI. The review feedback highlights three key issues: a regression in the model picker that removes the "auto" option for other pass-through providers, an issue where switching to Xiaomi with a "Max" reasoning effort silently disables thinking, and an overly restrictive model name normalization bypass that prevents the use of "auto" or custom models.

Comment on lines +92 to +96
let provider_models: &'static [(&'static str, &'static str)] = match app.api_provider {
crate::config::ApiProvider::Xiaomi => PICKER_MODELS_XIAOMI,
p if crate::config::provider_passes_model_through(p) => &[],
_ => PICKER_MODELS,
};
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

For other pass-through providers, setting provider_models to &[] removes the "auto" ("select per turn") option from the model picker, which is a regression from the previous behavior where vec!["auto"] was shown. We should return &[("auto", "select per turn")] for other pass-through providers to preserve this option.

Suggested change
let provider_models: &'static [(&'static str, &'static str)] = match app.api_provider {
crate::config::ApiProvider::Xiaomi => PICKER_MODELS_XIAOMI,
p if crate::config::provider_passes_model_through(p) => &[],
_ => PICKER_MODELS,
};
let provider_models: &'static [(&'static str, &'static str)] = match app.api_provider {
crate::config::ApiProvider::Xiaomi => PICKER_MODELS_XIAOMI,
p if crate::config::provider_passes_model_through(p) => &[("auto", "select per turn")],
_ => PICKER_MODELS,
};

Comment on lines +121 to +124
let selected_effort_idx = provider_efforts
.iter()
.position(|e| *e == normalized)
.unwrap_or(2); // default to High if somehow unknown
.unwrap_or(0); // default to first effort if unknown
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

If the user has ReasoningEffort::Max selected (which is common for DeepSeek), switching to Xiaomi MiMo will result in normalized being Max. Since PICKER_EFFORTS_MIMO does not contain Max, the position search will fail and default to 0 (ReasoningEffort::Off), silently disabling thinking. We should map ReasoningEffort::Max to ReasoningEffort::High when is_xiaomi is true.

        let selected_effort_idx = provider_efforts
            .iter()
            .position(|e| {
                if is_xiaomi && normalized == ReasoningEffort::Max {
                    *e == ReasoningEffort::High
                } else {
                    *e == normalized
                }
            })
            .unwrap_or(0);

Comment thread crates/tui/src/config.rs Outdated
Comment on lines +451 to +459
if matches!(provider, ApiProvider::Xiaomi) && trimmed.to_ascii_lowercase().starts_with("mimo") {
if trimmed
.chars()
.all(|ch| ch.is_ascii_alphanumeric() || matches!(ch, '-' | '_' | '.' | ':'))
{
return Some(trimmed.to_string());
}
return None;
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Restricting the bypass to only models starting with "mimo" prevents the use of "auto" (the special TUI-level model name for auto-selection) or any custom/fine-tuned models that do not follow the "mimo" prefix. Since Xiaomi is a pass-through provider, we should allow any valid model name format.

    if matches!(provider, ApiProvider::Xiaomi) {
        if trimmed
            .chars()
            .all(|ch| ch.is_ascii_alphanumeric() || matches!(ch, '-' | '_' | '.' | ':'))
        { 
            return Some(trimmed.to_string());
        }
        return None;
    }

Comment thread crates/tui/src/tui/model_picker.rs
Comment thread crates/tui/src/tui/model_picker.rs
Comment thread crates/tui/src/config.rs Outdated
Hmbown added a commit that referenced this pull request May 27, 2026
- New ProviderKind::Xiaomi across config, TUI, CLI, and agent crates
- Default endpoint: https://token-plan-cn.xiaomimimo.com/v1
- Models: mimo-v2.5-pro, mimo-v2.5, mimo-v2-flash
- MiMo-specific thinking toggle (enabled/disabled)
- /models command for Xiaomi provider
- Provider-specific model picker UI

Co-Authored-By: Hu Qiantao <huqiantao@HudeMacBook-Air.local>
Hu Qiantao and others added 8 commits May 27, 2026 10:56
Add first-class support for the Xiaomi MiMo API platform:

- New provider variant `Xiaomi` across config, TUI, CLI, and agent crates
- Default endpoint: https://api.xiaomimimo.com/v1
- Supports reasoning/thinking via reasoning_content field (same as DeepSeek)
- Model registry entries for mimo-v2.5-pro and mimo-v2-flash
- Provider picker, UI display names, and capability detection
- Environment variable: MIMO_API_KEY
- Example configuration in config.example.toml and .env.example

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- Remove unused DEFAULT_XIAOMI_FLASH_MODEL constant from config/src/lib.rs
- Add missing xiaomi field to ProvidersConfig struct and merge function
- Update picker_lists_all_providers test to include Xiaomi MiMo

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- Change default base_url to token-plan-cn.xiaomimimo.com/v1
  (Token Plan API, not pay-as-you-go)
- Add mimo-v2.5 (omni) model to registry with aliases
- Fix provider_capability: mimo-v2.5 gets 1M/128K context (not 256K)
  Logic now checks for "flash" instead of "pro" to correctly classify
- Update config examples with token-plan URLs, tp-xxxxx key format,
  and all three model options (pro/omni/flash)

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
When switching from DeepSeek to Xiaomi, the global default_text_model
("deepseek-v4-pro") was being inherited because Xiaomi is a pass-through
provider. Add dominated_model_prefix() guard to skip default_text_model
when it doesn't belong to the target provider's model namespace.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
The dominated_model_prefix guard broke the existing multi-provider
switching behavior where default_text_model is inherited across
providers. Users can set provider-specific models via the
[providers.xiaomi] config section instead.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…toggle

- Add provider-specific model list in /model picker (mimo-v2.5-pro, mimo-v2.5)
- Add provider-specific thinking effort (off/high only, MiMo doesn't support auto/max)
- Fix /models command to work with Xiaomi provider (fetches from /v1/models)
- Fix model validation to accept MiMo model names (not just DeepSeek)
- Fix thinking:off to send { type: "disabled" } instead of no-op for Xiaomi

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- Restore "auto" option for pass-through providers (OpenAI, Moonshot, etc.)
  that was accidentally removed in the model picker refactor
- Add mimo-v2-flash to PICKER_MODELS_XIAOMI so users can select it from /model
- Add mimo-v2.5 to model_completion_names_for_provider for tab-completion
- Map ReasoningEffort::Max → High when switching to Xiaomi (MiMo only supports
  on/off, so Max should map to High, not silently fall back to Off)
- Broaden Xiaomi model name validation to accept "auto" and custom models,
  not just "mimo"-prefixed names

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Remove all mimo-v2-flash references: model registry entry, picker list,
completion names, env/config examples, and the unused DEFAULT_XIAOMI_FLASH_MODEL
constant. Only mimo-v2.5-pro and mimo-v2.5 are supported.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@HUQIANTAO HUQIANTAO force-pushed the feat/xiaomi-mimo-support branch from 580e90d to af98fc1 Compare May 27, 2026 02:57
Hu Qiantao and others added 2 commits May 27, 2026 14:14
Adds MiMo provider usage examples, env var references, and capability
metadata across all three README languages, the provider registry, and
the configuration reference.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant