From 68acabd6a18fbeb8b5fe4408e297399232a29ca5 Mon Sep 17 00:00:00 2001 From: Augustin Date: Fri, 24 Apr 2026 21:22:34 +0200 Subject: [PATCH] feat(ai): add Xiaomi MiMo provider, ZAI as last-resort fallback MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add MiMo-V2.5-Pro from Xiaomi Token Plan as a new AI provider with base URL https://token-plan-ams.xiaomimimo.com/v1. The /model change command now switches between MiniMax and MiMo only. ZAI is always placed last in the fallback chain as the provider of ultimate resort. Config panel shows MiniMax and MiMo cards. 💘 Generated with Crush Assisted-by: GLM-5.1 via Crush --- internal/api/handlers_info.go | 5 +++++ internal/config/config.go | 6 ++++++ internal/orchestrator/orchestrator.go | 12 +++++++++++- web/src/components/Config.jsx | 2 +- web/src/components/Studio.jsx | 10 +++++----- 5 files changed, 28 insertions(+), 7 deletions(-) diff --git a/internal/api/handlers_info.go b/internal/api/handlers_info.go index e6ced66..921481a 100644 --- a/internal/api/handlers_info.go +++ b/internal/api/handlers_info.go @@ -530,6 +530,11 @@ func (s *Server) handleProvidersQuota(w http.ResponseWriter, r *http.Request) { } } } + case "mimo": + q.Healthy = p.APIKey != "" + if p.APIKey == "" { + q.Error = "no API key" + } case "claude", "anthropic": // Claude Code n'a pas d'API externe, vĂ©rifier l'installation claudePath := "/usr/bin/claude" diff --git a/internal/config/config.go b/internal/config/config.go index cb26ec0..ab693b1 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -269,6 +269,12 @@ func Default() *MuyueConfig { BaseURL: "https://api.minimax.io/v1", Active: true, }, + { + Name: "mimo", + Model: "MiMo-V2.5-Pro", + BaseURL: "https://token-plan-ams.xiaomimimo.com/v1", + Active: false, + }, { Name: "zai", Model: "glm", diff --git a/internal/orchestrator/orchestrator.go b/internal/orchestrator/orchestrator.go index 7c70887..235c41e 100644 --- a/internal/orchestrator/orchestrator.go +++ b/internal/orchestrator/orchestrator.go @@ -476,6 +476,8 @@ func getProviderBaseURL(name string) string { return "https://api.openai.com/v1" case "zai": return "https://api.z.ai/v1" + case "mimo": + return "https://token-plan-ams.xiaomimimo.com/v1" default: return "" } @@ -503,11 +505,19 @@ func (o *Orchestrator) sendWithFallback(reqBody ChatRequest, baseURLOverride str if o.provider != nil { providerOrder = append(providerOrder, o.provider) } + var zaiProvider *config.AIProvider for _, p := range providers { if o.provider == nil || p.Name != o.provider.Name { - providerOrder = append(providerOrder, p) + if p.Name == "zai" { + zaiProvider = p + } else { + providerOrder = append(providerOrder, p) + } } } + if zaiProvider != nil { + providerOrder = append(providerOrder, zaiProvider) + } var lastErr error var triedProviders []string diff --git a/web/src/components/Config.jsx b/web/src/components/Config.jsx index ac38210..1534c7b 100644 --- a/web/src/components/Config.jsx +++ b/web/src/components/Config.jsx @@ -343,7 +343,7 @@ function PanelProviders({ providers, editProvider, providerForm, setProviderForm setValidating(null) } - const displayed = providers.filter(p => p.name === 'minimax' || p.name === 'zai') + const displayed = providers.filter(p => p.name === 'minimax' || p.name === 'mimo') return (
diff --git a/web/src/components/Studio.jsx b/web/src/components/Studio.jsx index f49a53b..ca85ee0 100644 --- a/web/src/components/Studio.jsx +++ b/web/src/components/Studio.jsx @@ -452,15 +452,15 @@ export default function Studio({ api }) { api.getProviders().then(data => { const providers = data.providers || [] const minimax = providers.find(p => p.name.toUpperCase() === 'MINIMAX') - const zai = providers.find(p => p.name.toUpperCase() === 'ZAI') - if (!minimax || !zai) { - setMessages(prev => [...prev, { id: Date.now().toString(), role: 'assistant', content: 'MiniMax et ZAI doivent ĂȘtre configurĂ©s pour utiliser `/model change`.', time: new Date().toISOString() }]) + const mimo = providers.find(p => p.name.toUpperCase() === 'MIMO') + if (!minimax || !mimo) { + setMessages(prev => [...prev, { id: Date.now().toString(), role: 'assistant', content: 'MiniMax et MiMo doivent ĂȘtre configurĂ©s pour utiliser `/model change`.', time: new Date().toISOString() }]) return } const active = providers.find(p => p.active) const activeName = active ? active.name.toUpperCase() : '' - const switchTo = activeName === 'MINIMAX' ? 'ZAI' : 'MINIMAX' - const target = switchTo === 'MINIMAX' ? minimax : zai + const switchTo = activeName === 'MINIMAX' ? 'MIMO' : 'MINIMAX' + const target = switchTo === 'MINIMAX' ? minimax : mimo api.saveProvider({ name: target.name, active: true }).then(() => { setMessages(prev => [...prev, { id: Date.now().toString(), role: 'assistant', content: `✓ Provider changĂ©: **${target.name}** (${target.model})`, time: new Date().toISOString() }]) }).catch(() => {