Skip to content

feat: support Xiaomi MiMo Token Plan mode#2627

Open
xyuai wants to merge 1 commit into
Hmbown:mainfrom
xyuai:fix-xiaomi-mimo-token-plan-2621
Open

feat: support Xiaomi MiMo Token Plan mode#2627
xyuai wants to merge 1 commit into
Hmbown:mainfrom
xyuai:fix-xiaomi-mimo-token-plan-2621

Conversation

@xyuai
Copy link
Copy Markdown
Contributor

@xyuai xyuai commented Jun 3, 2026

Addresses #2621.

Summary

  • Add Xiaomi MiMo Token Plan mode via [providers.xiaomi_mimo].mode, with token-plan, token-plan-sgp, and token-plan-ams cluster aliases.
  • Prefer Token Plan tp-* key env aliases (XIAOMI_MIMO_TOKEN_PLAN_API_KEY, MIMO_TOKEN_PLAN_API_KEY) while preserving existing standard MiMo key aliases.
  • Select the documented Token Plan /v1 endpoints by mode and send api-key auth for Token Plan hosts, while keeping Authorization: Bearer for the standard MiMo endpoint.
  • Normalize Xiaomi MiMo chat / ASR / TTS model aliases and update README, sample config, and provider docs.

Notes

  • Xiaomi's current Token Plan docs describe subscription credits, conversion factors, and rate-limit quotas in the docs / console, but I did not find a documented balance API endpoint to poll. This PR wires the first-class endpoint/auth/model path and leaves live remaining-credit telemetry for a future documented API.

Tests

  • cargo test -p codewhale-config xiaomi_mimo
  • cargo test -p codewhale-secrets xiaomi_mimo_env_aliases_resolve
  • cargo test -p codewhale-tui --bin codewhale-tui xiaomi_mimo

Greptile Summary

Adds Xiaomi MiMo Token Plan mode support: a new mode config field (and XIAOMI_MIMO_MODE/MIMO_MODE env vars) selects the correct regional Token Plan endpoint, and the HTTP client now sends api-key auth instead of Authorization: Bearer when a Token Plan host or tp-* key is detected.

  • Config & env resolution (crates/config/src/lib.rs, crates/tui/src/config.rs): xiaomi_mimo_base_url_for_mode maps \"token-plan\", \"token-plan-sgp\", and \"token-plan-ams\" (plus locale aliases) to their documented endpoints; unknown non-standard modes fall through to the Token Plan CN default rather than silently reverting to the standard endpoint.
  • Auth header selection (crates/tui/src/client.rs): build_default_headers now receives ApiProvider and base_url; for XiaomiMimo it uses api-key: <key> when the base URL is a token-plan-*.xiaomimimo.com host or the key starts with tp- (covering custom-gateway scenarios), and Authorization: Bearer otherwise.
  • Secrets lookup (crates/secrets/src/lib.rs): XIAOMI_MIMO_TOKEN_PLAN_API_KEY / MIMO_TOKEN_PLAN_API_KEY are prepended to the candidate list for all Xiaomi MiMo connections, making them unconditionally highest priority regardless of configured mode.

Confidence Score: 4/5

Functionally correct for the common single-key case; the key lookup order in secrets is unconditional and can select a Token Plan key for a standard-endpoint connection when both key types are present in the environment.

The auth-header routing and mode-to-URL resolution are well-tested and handle edge cases correctly. The one concern is in crates/secrets/src/lib.rs: XIAOMI_MIMO_TOKEN_PLAN_API_KEY is now the highest-priority candidate for every Xiaomi MiMo connection. A user who has both a tp-* subscription key and a standard sk-* key in their environment but has not configured a Token Plan mode will have the TP key selected and sent with api-key auth to the standard endpoint, which is unlikely to accept it.

crates/secrets/src/lib.rs — the unconditional priority of XIAOMI_MIMO_TOKEN_PLAN_API_KEY affects users who maintain both key types simultaneously without an explicit mode setting.

Important Files Changed

Filename Overview
crates/secrets/src/lib.rs XIAOMI_MIMO_TOKEN_PLAN_API_KEY is now the highest-priority lookup for all Xiaomi MiMo connections regardless of whether mode selects a Token Plan endpoint; a user with both a tp-* key and a standard key will always use the Token Plan key
crates/tui/src/client.rs Adds api-key vs Authorization: Bearer selection for XiaomiMimo Token Plan; logic is well-tested and correctly falls back to key-prefix detection for custom gateways
crates/tui/src/config.rs Adds mode field to ProviderConfig, env override in apply_env_overrides, and duplicated xiaomi_mimo_base_url_for_mode / xiaomi_mimo_base_url_is_official functions; explicit base_url correctly wins over mode in deepseek_base_url()
crates/config/src/lib.rs Adds mode field, env resolution, and URL-selection helpers in the config crate; unknown mode values now stay on Token Plan CN instead of silently falling back to the standard endpoint; test coverage is thorough
docs/PROVIDERS.md Documents Token Plan mode values, api-key header behavior, and ASR model in the provider table; accurate and consistent with the implementation
README.md Adds Token Plan usage example and XIAOMI_MIMO_MODE/MIMO_MODE to the env-vars table
config.example.toml Adds mode comments for all three Token Plan clusters plus a custom base_url hint

Sequence Diagram

sequenceDiagram
    participant User
    participant EnvSecrets as Secrets (env_for)
    participant Config as Config Resolution
    participant Headers as build_default_headers
    participant Endpoint as XiaomiMimo API

    User->>EnvSecrets: Lookup key for "xiaomi-mimo"
    Note over EnvSecrets: Priority order:<br/>XIAOMI_MIMO_TOKEN_PLAN_API_KEY<br/>MIMO_TOKEN_PLAN_API_KEY<br/>XIAOMI_MIMO_API_KEY / XIAOMI_API_KEY / MIMO_API_KEY
    EnvSecrets-->>Config: First non-empty key found

    User->>Config: "Set mode = "token-plan-sgp" (env or TOML)"
    Config->>Config: "xiaomi_mimo_base_url_for_mode()<br/>→ https://token-plan-sgp.xiaomimimo.com/v1"
    Note over Config: Explicit base_url takes priority<br/>over mode-derived URL

    Config->>Headers: api_key, base_url, ApiProvider::XiaomiMimo

    alt "Token Plan base URL (token-plan-*.xiaomimimo.com)"
        Headers->>Headers: api-key: key
    else "tp-* key prefix (custom gateway)"
        Headers->>Headers: api-key: key
    else Standard key + standard endpoint
        Headers->>Headers: Authorization: Bearer key
    end

    Headers-->>Endpoint: HTTP request with correct auth header
Loading

Comments Outside Diff (3)

  1. crates/config/src/lib.rs, line 94-95 (link)

    P2 Redundant identical constants

    DEFAULT_XIAOMI_MIMO_TOKEN_PLAN_BASE_URL and XIAOMI_MIMO_TOKEN_PLAN_CN_BASE_URL are both "https://token-plan-cn.xiaomimimo.com/v1". Having two constants with the same value but different names suggests they might diverge in the future when they should always track the same URL (the CN cluster), making the code misleading. Callers that want "CN explicitly" and callers that want "default Token Plan" both resolve to the same string today, but a future change to the default cluster would silently break one or the other. The same duplication exists in crates/tui/src/config.rs lines 87–88.

    Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

    Fix in Codex Fix in Claude Code Fix in Cursor

  2. crates/config/src/lib.rs, line 1776-1803 (link)

    P2 xiaomi_mimo_token_plan_base_url_for_mode is duplicated across crates

    This function (including its match arms, normalization logic, and alias list) is copy-pasted verbatim into crates/tui/src/config.rs at fn xiaomi_mimo_token_plan_base_url_for_mode. The same duplication exists for xiaomi_mimo_base_url_is_official. Keeping two independent copies means that any future addition of a new cluster alias, a normalization fix, or a renamed variant must be applied twice, and the two implementations can silently diverge.

    Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

    Fix in Codex Fix in Claude Code Fix in Cursor

  3. crates/secrets/src/lib.rs, line 437-443 (link)

    P1 Token Plan key always takes priority regardless of active mode

    XIAOMI_MIMO_TOKEN_PLAN_API_KEY is now tried first for every Xiaomi MiMo connection, even when no Token Plan mode is active. A user who has both XIAOMI_MIMO_TOKEN_PLAN_API_KEY (a tp- key) and XIAOMI_MIMO_API_KEY (a standard sk- key) set in their environment — for example while managing both a subscription and a direct API account — will have the Token Plan key sent with Authorization: Bearer to the standard api.xiaomimimo.com endpoint. The standard endpoint is unlikely to accept Token Plan keys, so the request will fail with an opaque authentication error rather than falling through to the standard key. The new test explicitly confirms this priority (Some("token-plan-key")) but does not exercise the standard-endpoint path with both keys present.

    Fix in Codex Fix in Claude Code Fix in Cursor

Reviews (3): Last reviewed commit: "feat: support Xiaomi MiMo Token Plan mod..." | Re-trigger Greptile

@github-actions
Copy link
Copy Markdown

github-actions Bot commented Jun 3, 2026

Thanks @xyuai for taking the time to contribute.

This repository is currently observing a maintainer-managed contribution gate in dry-run mode, so this pull request is staying open. When enforcement is enabled, pull requests from contributors who are not listed in .github/APPROVED_CONTRIBUTORS will be closed automatically.

Please read CONTRIBUTING.md for the expected contribution shape. A maintainer can grant PR access by commenting /lgtm on a pull request.

@Hmbown
Copy link
Copy Markdown
Owner

Hmbown commented Jun 3, 2026

Thanks @xyuai for jumping on #2621 so quickly. I saw this come in during the v0.8.52 stabilization pass.

I am intentionally not pulling this into #2626: Token Plan changes endpoint selection, credential precedence, auth headers, model aliases, and docs, and the current PR checks are red. That makes it a good follow-up feature PR, not something to squeeze into the corrective 0.8.52 release.

After 0.8.52 is merged/released, this should get a normal provider-surface review: config/env/auth behavior, docs, provider-registry drift, and ideally live verification against a Token Plan key or official examples. Thanks again, and sorry the current release branch is noisy right now.

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 introduces support for Xiaomi MiMo Token Plan subscriptions, enabling the use of tp-* API keys with api-key header authentication and adding regional cluster configuration options (mode) via config files and environment variables. The review feedback suggests several improvements to the HTTP client implementation in crates/tui/src/client.rs: adding a fallback check for API keys starting with tp- to support custom base URLs, comparing HeaderName directly instead of converting to strings for the authorization header check, and simplifying the header filtering logic by leveraging case-insensitive HeaderName equality.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment thread crates/tui/src/client.rs
Comment on lines +665 to +674
let auth_header_name = if !api_key.is_empty()
&& api_provider == ApiProvider::XiaomiMimo
&& xiaomi_mimo_base_url_uses_token_plan(base_url)
{
Some(HeaderName::from_static("api-key"))
} else if !api_key.is_empty() {
Some(AUTHORIZATION)
} else {
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

For users utilizing a custom base_url (such as a local proxy, mock server, or internal load balancer) with the Xiaomi MiMo Token Plan, the xiaomi_mimo_base_url_uses_token_plan(base_url) check will return false because the domain won't match *.xiaomimimo.com. Since Token Plan API keys are documented to start with tp-, we can add a fallback check for api_key.starts_with("tp-") to ensure the correct api-key header is sent even when a custom base_url is used.

Suggested change
let auth_header_name = if !api_key.is_empty()
&& api_provider == ApiProvider::XiaomiMimo
&& xiaomi_mimo_base_url_uses_token_plan(base_url)
{
Some(HeaderName::from_static("api-key"))
} else if !api_key.is_empty() {
Some(AUTHORIZATION)
} else {
None
};
let auth_header_name = if !api_key.is_empty()
&& api_provider == ApiProvider::XiaomiMimo
&& (xiaomi_mimo_base_url_uses_token_plan(base_url) || api_key.starts_with("tp-"))
{
Some(HeaderName::from_static("api-key"))
} else if !api_key.is_empty() {
Some(AUTHORIZATION)
} else {
None
};

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Addressed in the latest push: tp-* Xiaomi MiMo keys now use api-key auth even when the request goes through a custom base URL / gateway, with a regression test covering the custom URL case.

Comment thread crates/tui/src/client.rs Outdated
None
};
if let Some(header_name) = auth_header_name.as_ref() {
let header_value = if header_name.as_str() == AUTHORIZATION.as_str() {
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

Comparing HeaderName directly is more idiomatic and efficient than comparing their string representations via .as_str(). We can simplify header_name.as_str() == AUTHORIZATION.as_str() to header_name == AUTHORIZATION.

Suggested change
let header_value = if header_name.as_str() == AUTHORIZATION.as_str() {
let header_value = if header_name == AUTHORIZATION {

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Addressed in the latest push by comparing HeaderName directly against AUTHORIZATION.

Comment thread crates/tui/src/client.rs Outdated
Comment on lines +692 to +694
|| auth_header_name
.as_ref()
.is_some_and(|auth| header_name.as_str().eq_ignore_ascii_case(auth.as_str()))
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

Since HeaderName equality is case-insensitive by default in the http crate, we can simplify the check to see if header_name matches auth_header_name by comparing them directly. This avoids string allocation, formatting, and manual case-insensitive string comparison.

Suggested change
|| auth_header_name
.as_ref()
.is_some_and(|auth| header_name.as_str().eq_ignore_ascii_case(auth.as_str()))
|| auth_header_name.as_ref() == Some(&header_name)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Addressed in the latest push by comparing auth_header_name.as_ref() == Some(&header_name) directly.

Comment thread crates/config/src/lib.rs Outdated
Comment thread crates/tui/src/config.rs
@xyuai xyuai force-pushed the fix-xiaomi-mimo-token-plan-2621 branch from 9190cb3 to 4d1c5cd Compare June 3, 2026 10:25
@xyuai
Copy link
Copy Markdown
Contributor Author

xyuai commented Jun 3, 2026

Updated this PR after the review feedback and rebased it onto the latest main (c8ce2b8e92b6366070308118e397cc97b3c4a220).

Follow-up changes:

  • Removed the undocumented orbit mode alias.
  • Unknown non-standard MiMo mode values now stay on the Token Plan CN endpoint instead of silently falling back to the standard endpoint/auth scheme.
  • tp-* MiMo keys now use api-key auth even with custom base URLs / gateways.
  • Simplified HeaderName comparisons as suggested.

Re-validated:

  • cargo test -p codewhale-config xiaomi_mimo
  • cargo test -p codewhale-secrets xiaomi_mimo_env_aliases_resolve
  • cargo test -p codewhale-tui --bin codewhale-tui xiaomi_mimo
  • cargo fmt -- --check
  • git diff --check

@xyuai xyuai force-pushed the fix-xiaomi-mimo-token-plan-2621 branch from 4d1c5cd to fbf88c9 Compare June 3, 2026 10:33
@xyuai
Copy link
Copy Markdown
Contributor Author

xyuai commented Jun 3, 2026

The two CI issues were from the previous run: Windows failed before tests in the cache restore step, which cancelled the macOS matrix leg. I refreshed the PR head to rerun CI; the latest run is now green across GitGuardian, GitHub Actions, and Greptile, including Test (windows-latest) and Test (macos-latest).

@Hmbown
Copy link
Copy Markdown
Owner

Hmbown commented Jun 3, 2026

Thanks for the quick follow-up @xyuai. I see the refreshed CI is green now, including macOS and Windows, and the narrower Token Plan behavior is a much better review surface.

I am still keeping this out of the corrective 0.8.52 release because it is a new provider sub-mode that changes endpoint/auth/model behavior and really deserves live verification against Xiaomi Token Plan docs or a test key before it ships as first-class. This should get a normal provider review right after 0.8.52 is fully repaired/published rather than being lost in the release cleanup. Appreciate the fast cleanup here.

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.

2 participants