From 78b98766413a5b95150841592a194c34dfd6527d Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Thu, 29 Jan 2026 17:29:58 +0000 Subject: [PATCH] feat: add Xiaomi MiMo provider onboarding (#3454) Thanks @WqyJh. Co-authored-by: Qiying Wang <15232241+WqyJh@users.noreply.github.com> --- CHANGELOG.md | 1 + src/agents/models-config.providers.ts | 2 +- ...s-writing-models-json-no-env-token.test.ts | 4 ++ src/commands/onboard-auth.config-core.ts | 11 ++++- src/commands/onboard-auth.test.ts | 46 +++++++++++++++++++ 5 files changed, 61 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b6e8445bc..208b64a8d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,7 @@ Status: beta. ### Changes - Providers: add Venice AI integration; update Moonshot Kimi references to kimi-k2.5; update MiniMax API endpoint/format. (#2762, #3064) +- Providers: add Xiaomi MiMo (mimo-v2-flash) support and onboarding flow. (#3454) Thanks @WqyJh. - Telegram: quote replies, edit-message action, silent sends, sticker support + vision caching, linkPreview toggle, plugin sendPayload support. (#2900, #2394, #2382, #2548, #1700, #1917) - Discord: configurable privileged gateway intents for presences/members. (#2266) Thanks @kentaro. - Browser: route browser control via gateway/node; fallback URL matching for relay targets. (#1999) diff --git a/src/agents/models-config.providers.ts b/src/agents/models-config.providers.ts index 9ed0d1737..f38ad46c7 100644 --- a/src/agents/models-config.providers.ts +++ b/src/agents/models-config.providers.ts @@ -31,7 +31,7 @@ const MINIMAX_API_COST = { }; const XIAOMI_BASE_URL = "https://api.xiaomimimo.com/anthropic"; -const XIAOMI_DEFAULT_MODEL_ID = "mimo-v2-flash"; +export const XIAOMI_DEFAULT_MODEL_ID = "mimo-v2-flash"; const XIAOMI_DEFAULT_CONTEXT_WINDOW = 262144; const XIAOMI_DEFAULT_MAX_TOKENS = 8192; const XIAOMI_DEFAULT_COST = { diff --git a/src/agents/models-config.skips-writing-models-json-no-env-token.test.ts b/src/agents/models-config.skips-writing-models-json-no-env-token.test.ts index fef8fa6a4..08a66469f 100644 --- a/src/agents/models-config.skips-writing-models-json-no-env-token.test.ts +++ b/src/agents/models-config.skips-writing-models-json-no-env-token.test.ts @@ -53,6 +53,7 @@ describe("models-config", () => { const previousMoonshot = process.env.MOONSHOT_API_KEY; const previousSynthetic = process.env.SYNTHETIC_API_KEY; const previousVenice = process.env.VENICE_API_KEY; + const previousXiaomi = process.env.XIAOMI_API_KEY; delete process.env.COPILOT_GITHUB_TOKEN; delete process.env.GH_TOKEN; delete process.env.GITHUB_TOKEN; @@ -61,6 +62,7 @@ describe("models-config", () => { delete process.env.MOONSHOT_API_KEY; delete process.env.SYNTHETIC_API_KEY; delete process.env.VENICE_API_KEY; + delete process.env.XIAOMI_API_KEY; try { vi.resetModules(); @@ -93,6 +95,8 @@ describe("models-config", () => { else process.env.SYNTHETIC_API_KEY = previousSynthetic; if (previousVenice === undefined) delete process.env.VENICE_API_KEY; else process.env.VENICE_API_KEY = previousVenice; + if (previousXiaomi === undefined) delete process.env.XIAOMI_API_KEY; + else process.env.XIAOMI_API_KEY = previousXiaomi; } }); }); diff --git a/src/commands/onboard-auth.config-core.ts b/src/commands/onboard-auth.config-core.ts index 3a585a6d0..222f0a5c6 100644 --- a/src/commands/onboard-auth.config-core.ts +++ b/src/commands/onboard-auth.config-core.ts @@ -1,4 +1,4 @@ -import { buildXiaomiProvider } from "../agents/models-config.providers.js"; +import { buildXiaomiProvider, XIAOMI_DEFAULT_MODEL_ID } from "../agents/models-config.providers.js"; import { buildSyntheticModelDefinition, SYNTHETIC_BASE_URL, @@ -349,7 +349,14 @@ export function applyXiaomiProviderConfig(cfg: MoltbotConfig): MoltbotConfig { const existingProvider = providers.xiaomi; const defaultProvider = buildXiaomiProvider(); const existingModels = Array.isArray(existingProvider?.models) ? existingProvider.models : []; - const mergedModels = existingModels.length > 0 ? existingModels : (defaultProvider.models ?? []); + const defaultModels = defaultProvider.models ?? []; + const hasDefaultModel = existingModels.some((model) => model.id === XIAOMI_DEFAULT_MODEL_ID); + const mergedModels = + existingModels.length > 0 + ? hasDefaultModel + ? existingModels + : [...existingModels, ...defaultModels] + : defaultModels; const { apiKey: existingApiKey, ...existingProviderRest } = (existingProvider ?? {}) as Record< string, unknown diff --git a/src/commands/onboard-auth.test.ts b/src/commands/onboard-auth.test.ts index 0a2c67f94..80d71852c 100644 --- a/src/commands/onboard-auth.test.ts +++ b/src/commands/onboard-auth.test.ts @@ -15,6 +15,8 @@ import { applyOpenrouterProviderConfig, applySyntheticConfig, applySyntheticProviderConfig, + applyXiaomiConfig, + applyXiaomiProviderConfig, OPENROUTER_DEFAULT_MODEL_REF, SYNTHETIC_DEFAULT_MODEL_ID, SYNTHETIC_DEFAULT_MODEL_REF, @@ -343,6 +345,50 @@ describe("applySyntheticConfig", () => { }); }); +describe("applyXiaomiConfig", () => { + it("adds Xiaomi provider with correct settings", () => { + const cfg = applyXiaomiConfig({}); + expect(cfg.models?.providers?.xiaomi).toMatchObject({ + baseUrl: "https://api.xiaomimimo.com/anthropic", + api: "anthropic-messages", + }); + expect(cfg.agents?.defaults?.model?.primary).toBe("xiaomi/mimo-v2-flash"); + }); + + it("merges Xiaomi models and keeps existing provider overrides", () => { + const cfg = applyXiaomiProviderConfig({ + models: { + providers: { + xiaomi: { + baseUrl: "https://old.example.com", + apiKey: "old-key", + api: "openai-completions", + models: [ + { + id: "custom-model", + name: "Custom", + reasoning: false, + input: ["text"], + cost: { input: 1, output: 2, cacheRead: 0, cacheWrite: 0 }, + contextWindow: 1000, + maxTokens: 100, + }, + ], + }, + }, + }, + }); + + expect(cfg.models?.providers?.xiaomi?.baseUrl).toBe("https://api.xiaomimimo.com/anthropic"); + expect(cfg.models?.providers?.xiaomi?.api).toBe("anthropic-messages"); + expect(cfg.models?.providers?.xiaomi?.apiKey).toBe("old-key"); + expect(cfg.models?.providers?.xiaomi?.models.map((m) => m.id)).toEqual([ + "custom-model", + "mimo-v2-flash", + ]); + }); +}); + describe("applyOpencodeZenProviderConfig", () => { it("adds allowlist entry for the default model", () => { const cfg = applyOpencodeZenProviderConfig({});