From d7a5cfe13c0eea53924a66b6ef296236652697cf Mon Sep 17 00:00:00 2001 From: openclaw Date: Fri, 8 May 2026 01:36:34 +0800 Subject: [PATCH 1/9] feat(models): add Xiaomi MiMo model family Add Xiaomi as a new provider and register all MiMo models: - mimo-v2.5-pro: 1T params, 42B activations, 1M context, deep thinking - mimo-v2-pro: 1T params, 42B active, 1M context, hybrid attention - mimo-v2.5: Full-modal perception (vision+audio+text), 1M context - mimo-v2-omni: Multimodal (text+vision+speech), 256K context - mimo-v2-flash: High-efficiency inference, 256K context Provider endpoint: https://api.xiaomimimo.com/v1 Pricing tiers based on official platform.xiaomimimo.com rates. --- packages/actions/src/get-provider-endpoint.ts | 4 + packages/models/src/models.ts | 2 + packages/models/src/models/xiaomi.ts | 181 ++++++++++++++++++ packages/models/src/providers.ts | 16 ++ 4 files changed, 203 insertions(+) create mode 100644 packages/models/src/models/xiaomi.ts diff --git a/packages/actions/src/get-provider-endpoint.ts b/packages/actions/src/get-provider-endpoint.ts index 3e953d13ff..2dc0d44652 100644 --- a/packages/actions/src/get-provider-endpoint.ts +++ b/packages/actions/src/get-provider-endpoint.ts @@ -228,6 +228,9 @@ export function getProviderEndpoint( case "minimax": url = "https://api.minimax.io"; break; + case "xiaomi": + url = "https://api.xiaomimimo.com"; + break; case "aws-bedrock": url = envValueOrDefault( @@ -487,6 +490,7 @@ export function getProviderEndpoint( case "nebius": case "nanogpt": case "minimax": + case "xiaomi": case "embercloud": case "custom": default: diff --git a/packages/models/src/models.ts b/packages/models/src/models.ts index 93dddbc5ff..4f669f905f 100644 --- a/packages/models/src/models.ts +++ b/packages/models/src/models.ts @@ -13,6 +13,7 @@ import { nousresearchModels } from "./models/nousresearch.js"; import { openaiModels } from "./models/openai.js"; import { perplexityModels } from "./models/perplexity.js"; import { xaiModels } from "./models/xai.js"; +import { xiaomiModels } from "./models/xiaomi.js"; import { zaiModels } from "./models/zai.js"; import type { providers } from "./providers.js"; @@ -433,6 +434,7 @@ export const models = [ ...googleModels, ...perplexityModels, ...xaiModels, + ...xiaomiModels, ...metaModels, ...deepseekModels, ...mistralModels, diff --git a/packages/models/src/models/xiaomi.ts b/packages/models/src/models/xiaomi.ts new file mode 100644 index 0000000000..17fe28e220 --- /dev/null +++ b/packages/models/src/models/xiaomi.ts @@ -0,0 +1,181 @@ +import type { ModelDefinition } from "@/models.js"; + +export const xiaomiModels = [ + { + id: "mimo-v2.5-pro", + name: "MiMo V2.5 Pro", + description: + "Xiaomi's flagship 1T-parameter model with 42B activations, 1M ultra-long context, and deep thinking capabilities. Performs comparably to Claude Opus 4.6 in agent scenarios.", + family: "xiaomi", + releasedAt: new Date("2026-04-23"), + providers: [ + { + providerId: "xiaomi" as const, + modelName: "mimo-v2.5-pro", + inputPrice: 1 / 1e6, + outputPrice: 3 / 1e6, + cachedInputPrice: 0.2 / 1e6, + requestPrice: 0, + contextSize: 1000000, + maxOutput: 131072, + streaming: true, + reasoning: true, + reasoningOutput: "omit" as const, + vision: false, + tools: true, + jsonOutput: true, + pricingTiers: [ + { + name: "256K", + upToTokens: 256000, + inputPrice: 1 / 1e6, + outputPrice: 3 / 1e6, + cachedInputPrice: 0.2 / 1e6, + }, + { + name: "1M", + upToTokens: 1000000, + inputPrice: 2 / 1e6, + outputPrice: 6 / 1e6, + cachedInputPrice: 0.4 / 1e6, + }, + ], + }, + ], + }, + { + id: "mimo-v2-pro", + name: "MiMo V2 Pro", + description: + "Xiaomi's 1T-parameter model with 42B active parameters and 1M context window using hybrid Global Attention + SWA architecture.", + family: "xiaomi", + releasedAt: new Date("2026-03-18"), + providers: [ + { + providerId: "xiaomi" as const, + modelName: "mimo-v2-pro", + inputPrice: 1 / 1e6, + outputPrice: 3 / 1e6, + cachedInputPrice: 0.2 / 1e6, + requestPrice: 0, + contextSize: 1000000, + maxOutput: 131072, + streaming: true, + reasoning: true, + reasoningOutput: "omit" as const, + vision: false, + tools: true, + jsonOutput: true, + pricingTiers: [ + { + name: "256K", + upToTokens: 256000, + inputPrice: 1 / 1e6, + outputPrice: 3 / 1e6, + cachedInputPrice: 0.2 / 1e6, + }, + { + name: "1M", + upToTokens: 1000000, + inputPrice: 2 / 1e6, + outputPrice: 6 / 1e6, + cachedInputPrice: 0.4 / 1e6, + }, + ], + }, + ], + }, + { + id: "mimo-v2.5", + name: "MiMo V2.5", + description: + "Xiaomi's full-modal perception model supporting native understanding of images, videos, audio, and text with 1M context. Agent performance comparable to MiMo V2.5 Pro.", + family: "xiaomi", + releasedAt: new Date("2026-04-23"), + providers: [ + { + providerId: "xiaomi" as const, + modelName: "mimo-v2.5", + inputPrice: 0.4 / 1e6, + outputPrice: 2 / 1e6, + cachedInputPrice: 0.08 / 1e6, + requestPrice: 0, + contextSize: 1000000, + maxOutput: 131072, + streaming: true, + reasoning: true, + reasoningOutput: "omit" as const, + vision: true, + tools: true, + jsonOutput: true, + pricingTiers: [ + { + name: "256K", + upToTokens: 256000, + inputPrice: 0.4 / 1e6, + outputPrice: 2 / 1e6, + cachedInputPrice: 0.08 / 1e6, + }, + { + name: "1M", + upToTokens: 1000000, + inputPrice: 0.8 / 1e6, + outputPrice: 4 / 1e6, + cachedInputPrice: 0.16 / 1e6, + }, + ], + }, + ], + }, + { + id: "mimo-v2-omni", + name: "MiMo V2 Omni", + description: + "Xiaomi's multimodal model supporting text, vision, and speech modalities with 256K context window.", + family: "xiaomi", + releasedAt: new Date("2026-03-18"), + providers: [ + { + providerId: "xiaomi" as const, + modelName: "mimo-v2-omni", + inputPrice: 0.4 / 1e6, + outputPrice: 2 / 1e6, + cachedInputPrice: 0.08 / 1e6, + requestPrice: 0, + contextSize: 256000, + maxOutput: 131072, + streaming: true, + reasoning: false, + vision: true, + tools: true, + jsonOutput: true, + }, + ], + }, + { + id: "mimo-v2-flash", + name: "MiMo V2 Flash", + description: + "Xiaomi's high-efficiency inference model with hybrid architecture, 3 MTP layers for 2.5-3.7x faster inference, and 256K context.", + family: "xiaomi", + releasedAt: new Date("2025-12-16"), + providers: [ + { + providerId: "xiaomi" as const, + modelName: "mimo-v2-flash", + inputPrice: 0.1 / 1e6, + outputPrice: 0.3 / 1e6, + cachedInputPrice: 0.01 / 1e6, + requestPrice: 0, + contextSize: 256000, + maxOutput: undefined, + streaming: true, + reasoning: true, + reasoningOutput: "omit" as const, + vision: false, + tools: true, + jsonOutput: true, + }, + ], + }, +] as const satisfies ModelDefinition[]; diff --git a/packages/models/src/providers.ts b/packages/models/src/providers.ts index 5d5d86b19d..219ac05834 100644 --- a/packages/models/src/providers.ts +++ b/packages/models/src/providers.ts @@ -566,6 +566,22 @@ export const providers = [ website: "https://www.embercloud.ai", announcement: null, }, + { + id: "xiaomi", + name: "Xiaomi", + description: + "Xiaomi MiMo API Open Platform provides access to the MiMo series of large language models.", + env: { + required: { + apiKey: "LLM_XIAOMI_API_KEY", + }, + }, + streaming: true, + cancellation: true, + color: "#FF6900", + website: "https://platform.xiaomimimo.com", + announcement: null, + }, ] as const satisfies ProviderDefinition[]; export type ProviderId = (typeof providers)[number]["id"]; From 76ce63eb75c8a457e52b91f1e0b40b3fb09fea2c Mon Sep 17 00:00:00 2001 From: openclaw Date: Fri, 8 May 2026 01:49:20 +0800 Subject: [PATCH 2/9] feat(xiaomi): add e2e tests, configurable base URL, env examples - Add 3 endpoint tests for xiaomi provider (default, custom URL, streaming) - Make base URL configurable via LLM_XIAOMI_BASE_URL env var - Add LLM_XIAOMI_API_KEY to .env.example and .env.unified.example - Verified all 5 models work via live API (basic, streaming, tool calling) Co-authored-by: openclaw --- .env.example | 4 +++ .env.unified.example | 4 +++ .../actions/src/get-provider-endpoint.spec.ts | 36 +++++++++++++++++++ packages/actions/src/get-provider-endpoint.ts | 7 +++- packages/models/src/providers.ts | 3 ++ 5 files changed, 53 insertions(+), 1 deletion(-) diff --git a/.env.example b/.env.example index 19535567d5..d6119b0ed5 100644 --- a/.env.example +++ b/.env.example @@ -170,6 +170,10 @@ LLM_GROQ_API_KEY=your_groq_key_here # DeepSeek LLM_DEEPSEEK_API_KEY=your_deepseek_key_here +# Xiaomi MiMo +LLM_XIAOMI_API_KEY=your_xiaomi_key_here +# LLM_XIAOMI_BASE_URL=https://api.xiaomimimo.com + # Perplexity LLM_PERPLEXITY_API_KEY=your_perplexity_key_here diff --git a/.env.unified.example b/.env.unified.example index df67dcffab..4215d7e285 100644 --- a/.env.unified.example +++ b/.env.unified.example @@ -83,6 +83,10 @@ LLM_GROQ_API_KEY=your_groq_key_here # DeepSeek LLM_DEEPSEEK_API_KEY=your_deepseek_key_here +# Xiaomi MiMo +LLM_XIAOMI_API_KEY=your_xiaomi_key_here +# LLM_XIAOMI_BASE_URL=https://api.xiaomimimo.com + # Perplexity LLM_PERPLEXITY_API_KEY=your_perplexity_key_here diff --git a/packages/actions/src/get-provider-endpoint.spec.ts b/packages/actions/src/get-provider-endpoint.spec.ts index b780a7bbab..e16b216fd2 100644 --- a/packages/actions/src/get-provider-endpoint.spec.ts +++ b/packages/actions/src/get-provider-endpoint.spec.ts @@ -249,6 +249,42 @@ describe("getProviderEndpoint", () => { }); }); + describe("xiaomi", () => { + it("builds the default Xiaomi endpoint", () => { + const endpoint = getProviderEndpoint( + "xiaomi", + undefined, + "mimo-v2.5-pro", + ); + + expect(endpoint).toBe("https://api.xiaomimimo.com/v1/chat/completions"); + }); + + it("uses custom base URL when provided", () => { + const endpoint = getProviderEndpoint( + "xiaomi", + "https://custom-xiaomi.example.com", + "mimo-v2-flash", + ); + + expect(endpoint).toBe( + "https://custom-xiaomi.example.com/v1/chat/completions", + ); + }); + + it("builds streaming endpoint", () => { + const endpoint = getProviderEndpoint( + "xiaomi", + undefined, + "mimo-v2.5", + undefined, + true, + ); + + expect(endpoint).toBe("https://api.xiaomimimo.com/v1/chat/completions"); + }); + }); + describe("skipEnvVars (BYOK mode)", () => { it("uses hardcoded default for google-ai-studio instead of env var", () => { process.env.LLM_GOOGLE_AI_STUDIO_BASE_URL = diff --git a/packages/actions/src/get-provider-endpoint.ts b/packages/actions/src/get-provider-endpoint.ts index 2dc0d44652..c7cf9c9adb 100644 --- a/packages/actions/src/get-provider-endpoint.ts +++ b/packages/actions/src/get-provider-endpoint.ts @@ -229,7 +229,12 @@ export function getProviderEndpoint( url = "https://api.minimax.io"; break; case "xiaomi": - url = "https://api.xiaomimimo.com"; + url = + envValueOrDefault( + "xiaomi", + "baseUrl", + "https://api.xiaomimimo.com", + ) ?? "https://api.xiaomimimo.com"; break; case "aws-bedrock": url = diff --git a/packages/models/src/providers.ts b/packages/models/src/providers.ts index 219ac05834..e200ad340d 100644 --- a/packages/models/src/providers.ts +++ b/packages/models/src/providers.ts @@ -575,6 +575,9 @@ export const providers = [ required: { apiKey: "LLM_XIAOMI_API_KEY", }, + optional: { + baseUrl: "LLM_XIAOMI_BASE_URL", + }, }, streaming: true, cancellation: true, From ad0e465008ef68d2071a8441cb67cf81b0e785b3 Mon Sep 17 00:00:00 2001 From: openclaw Date: Fri, 8 May 2026 01:53:36 +0800 Subject: [PATCH 3/9] docs(xiaomi): clarify mimo-v2-flash 10% cache discount is intentional The flash model has a distinct 10% cached-read discount ratio (0.01/0.10) per official pricing, unlike other MiMo models at 20%. --- packages/models/src/models/xiaomi.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/models/src/models/xiaomi.ts b/packages/models/src/models/xiaomi.ts index 17fe28e220..1d3496816c 100644 --- a/packages/models/src/models/xiaomi.ts +++ b/packages/models/src/models/xiaomi.ts @@ -165,6 +165,7 @@ export const xiaomiModels = [ modelName: "mimo-v2-flash", inputPrice: 0.1 / 1e6, outputPrice: 0.3 / 1e6, + // Flash model uses a 10% cache discount (not 20% like other MiMo models) cachedInputPrice: 0.01 / 1e6, requestPrice: 0, contextSize: 256000, From 0dc5293d88397d6922ff5777802d126cbf850475 Mon Sep 17 00:00:00 2001 From: Luca Steeb Date: Fri, 8 May 2026 01:01:22 +0700 Subject: [PATCH 4/9] ci: add LLM_XIAOMI_API_KEY to e2e workflow --- .github/workflows/e2e.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/e2e.yml b/.github/workflows/e2e.yml index 5751a397ae..8960f14588 100644 --- a/.github/workflows/e2e.yml +++ b/.github/workflows/e2e.yml @@ -83,6 +83,7 @@ jobs: LLM_EMBERCLOUD_API_KEY: ${{ secrets.LLM_EMBERCLOUD_API_KEY }} LLM_ALIBABA_API_KEY__US_VIRGINIA: ${{ secrets.LLM_ALIBABA_API_KEY__US_VIRGINIA }} LLM_ALIBABA_API_KEY__CN_BEIJING: ${{ secrets.LLM_ALIBABA_API_KEY__CN_BEIJING }} + LLM_XIAOMI_API_KEY: ${{ secrets.LLM_XIAOMI_API_KEY }} - name: Upload shard results if: always() From 7e2a4ecdcf6fbb5f2a8404455ee16fa401993bb1 Mon Sep 17 00:00:00 2001 From: openclaw Date: Fri, 8 May 2026 02:03:33 +0800 Subject: [PATCH 5/9] fix(test): save/restore LLM_XIAOMI_BASE_URL in endpoint tests Add LLM_XIAOMI_BASE_URL to the save/restore pattern in afterEach, and delete it at the start of tests that assert against the default URL. Prevents false failures when the env var is set in the test environment. --- packages/actions/src/get-provider-endpoint.spec.ts | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/packages/actions/src/get-provider-endpoint.spec.ts b/packages/actions/src/get-provider-endpoint.spec.ts index e16b216fd2..80858d86b7 100644 --- a/packages/actions/src/get-provider-endpoint.spec.ts +++ b/packages/actions/src/get-provider-endpoint.spec.ts @@ -10,6 +10,7 @@ const originalVertexRegion = process.env.LLM_GOOGLE_VERTEX_REGION; const originalAzureFoundryResource = process.env.LLM_AZURE_AI_FOUNDRY_RESOURCE; const originalAzureFoundryApiVersion = process.env.LLM_AZURE_AI_FOUNDRY_API_VERSION; +const originalXiaomiBaseUrl = process.env.LLM_XIAOMI_BASE_URL; afterEach(() => { if (originalAiStudioBaseUrl === undefined) { @@ -54,6 +55,12 @@ afterEach(() => { process.env.LLM_AZURE_AI_FOUNDRY_API_VERSION = originalAzureFoundryApiVersion; } + + if (originalXiaomiBaseUrl === undefined) { + delete process.env.LLM_XIAOMI_BASE_URL; + } else { + process.env.LLM_XIAOMI_BASE_URL = originalXiaomiBaseUrl; + } }); describe("getProviderEndpoint", () => { @@ -251,6 +258,8 @@ describe("getProviderEndpoint", () => { describe("xiaomi", () => { it("builds the default Xiaomi endpoint", () => { + delete process.env.LLM_XIAOMI_BASE_URL; + const endpoint = getProviderEndpoint( "xiaomi", undefined, @@ -273,6 +282,8 @@ describe("getProviderEndpoint", () => { }); it("builds streaming endpoint", () => { + delete process.env.LLM_XIAOMI_BASE_URL; + const endpoint = getProviderEndpoint( "xiaomi", undefined, From 155f3a72c9847b78e554703db7baac0d573e2101 Mon Sep 17 00:00:00 2001 From: openclaw Date: Fri, 8 May 2026 02:08:38 +0800 Subject: [PATCH 6/9] feat(ui): add Xiaomi provider icon Add XiaomiIcon SVG component and register it in ProviderIcons and providerLogoUrls maps. Uses the official Xiaomi logo with orange rounded-rect background and white 'mi' lettering. --- .../shared/src/components/provider-icons.tsx | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/packages/shared/src/components/provider-icons.tsx b/packages/shared/src/components/provider-icons.tsx index eebcff98d9..0b7efd5865 100644 --- a/packages/shared/src/components/provider-icons.tsx +++ b/packages/shared/src/components/provider-icons.tsx @@ -979,6 +979,22 @@ export const MinimaxIcon: React.FC> = (props) => { ); }; +// Xiaomi Icon +export const XiaomiIcon: React.FC> = (props) => ( + + + + +); + export const EmberCloudIcon: React.FC> = ( props, ) => ( @@ -1026,6 +1042,7 @@ export const ProviderIcons = { "azure-ai-foundry": AzureIcon, cerebras: CerebrasIcon, minimax: MinimaxIcon, + xiaomi: XiaomiIcon, embercloud: EmberCloudIcon, } as const; @@ -1060,6 +1077,7 @@ export const providerLogoUrls: Partial< "azure-ai-foundry": ProviderIcons["azure-ai-foundry"], cerebras: ProviderIcons.cerebras, minimax: ProviderIcons.minimax, + xiaomi: ProviderIcons.xiaomi, embercloud: ProviderIcons.embercloud, }; From 45a762f4f5a82e32c0ff4535185bef381b37d9b2 Mon Sep 17 00:00:00 2001 From: openclaw Date: Fri, 8 May 2026 02:12:02 +0800 Subject: [PATCH 7/9] fix(ui): add xiaomi icon to provider-keys logo mapping The provider-keys component has its own providerLogoUrls map that was missing xiaomi (and a few other newer providers). Added xiaomi plus azure-ai-foundry, minimax, bytedance, and embercloud for completeness. --- apps/ui/src/components/provider-keys/provider-logo.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/apps/ui/src/components/provider-keys/provider-logo.ts b/apps/ui/src/components/provider-keys/provider-logo.ts index 200d750707..c0d3fea6d7 100644 --- a/apps/ui/src/components/provider-keys/provider-logo.ts +++ b/apps/ui/src/components/provider-keys/provider-logo.ts @@ -26,7 +26,12 @@ export const providerLogoUrls: Partial< nanogpt: ProviderIcons.nanogpt, "aws-bedrock": ProviderIcons["aws-bedrock"], azure: ProviderIcons.azure, + "azure-ai-foundry": ProviderIcons["azure-ai-foundry"], cerebras: ProviderIcons.cerebras, + minimax: ProviderIcons.minimax, + bytedance: ProviderIcons.bytedance, + xiaomi: ProviderIcons.xiaomi, + embercloud: ProviderIcons.embercloud, }; export const getProviderLogoDarkModeClasses = () => { From 2af8907362ed03435641f484bbf3130c9e3bf079 Mon Sep 17 00:00:00 2001 From: Luca Steeb Date: Fri, 8 May 2026 01:23:52 +0700 Subject: [PATCH 8/9] fix(gateway): register xiaomi for openai-compatible streaming --- apps/gateway/src/chat/tools/transform-streaming-to-openai.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/gateway/src/chat/tools/transform-streaming-to-openai.ts b/apps/gateway/src/chat/tools/transform-streaming-to-openai.ts index 13ccc5d21c..b24ebe36d0 100644 --- a/apps/gateway/src/chat/tools/transform-streaming-to-openai.ts +++ b/apps/gateway/src/chat/tools/transform-streaming-to-openai.ts @@ -1304,6 +1304,7 @@ export function transformStreamingToOpenai( case "bytedance": case "minimax": case "embercloud": + case "xiaomi": case "azure-ai-foundry": case "llmgateway": { // Azure AI Foundry mirrors Azure OpenAI's prompt-filter-only leading From ca28db4894da9f52628cee12617882a01e8acb57 Mon Sep 17 00:00:00 2001 From: openclaw Date: Fri, 8 May 2026 02:53:23 +0800 Subject: [PATCH 9/9] fix(xiaomi): remove reasoningOutput omit for models that return reasoning content - mimo-v2.5-pro, mimo-v2-pro, mimo-v2.5: confirmed to return reasoning_content - mimo-v2-flash: keeps reasoningOutput omit (no reasoning_content in response) - Verified via e2e tests: all 3 reasoning models pass --- packages/models/src/models/xiaomi.ts | 3 --- 1 file changed, 3 deletions(-) diff --git a/packages/models/src/models/xiaomi.ts b/packages/models/src/models/xiaomi.ts index 1d3496816c..7e31fb06a6 100644 --- a/packages/models/src/models/xiaomi.ts +++ b/packages/models/src/models/xiaomi.ts @@ -20,7 +20,6 @@ export const xiaomiModels = [ maxOutput: 131072, streaming: true, reasoning: true, - reasoningOutput: "omit" as const, vision: false, tools: true, jsonOutput: true, @@ -62,7 +61,6 @@ export const xiaomiModels = [ maxOutput: 131072, streaming: true, reasoning: true, - reasoningOutput: "omit" as const, vision: false, tools: true, jsonOutput: true, @@ -104,7 +102,6 @@ export const xiaomiModels = [ maxOutput: 131072, streaming: true, reasoning: true, - reasoningOutput: "omit" as const, vision: true, tools: true, jsonOutput: true,