diff --git a/src/renderer/src/aiCore/utils/reasoning.ts b/src/renderer/src/aiCore/utils/reasoning.ts index f182405714..dad9d351b8 100644 --- a/src/renderer/src/aiCore/utils/reasoning.ts +++ b/src/renderer/src/aiCore/utils/reasoning.ts @@ -28,6 +28,7 @@ import { isSupportedThinkingTokenDoubaoModel, isSupportedThinkingTokenGeminiModel, isSupportedThinkingTokenHunyuanModel, + isSupportedThinkingTokenMiMoModel, isSupportedThinkingTokenModel, isSupportedThinkingTokenQwenModel, isSupportedThinkingTokenZhipuModel @@ -408,6 +409,12 @@ export function getReasoningEffort(assistant: Assistant, model: Model): Reasonin return { thinking: { type: 'enabled' } } } + if (isSupportedThinkingTokenMiMoModel(model)) { + return { + thinking: { type: 'enabled' } + } + } + // Default case: no special thinking settings return {} } diff --git a/src/renderer/src/assets/images/models/mimo.svg b/src/renderer/src/assets/images/models/mimo.svg new file mode 100644 index 0000000000..82370fece3 --- /dev/null +++ b/src/renderer/src/assets/images/models/mimo.svg @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/src/renderer/src/assets/images/providers/mimo.svg b/src/renderer/src/assets/images/providers/mimo.svg new file mode 100644 index 0000000000..82370fece3 --- /dev/null +++ b/src/renderer/src/assets/images/providers/mimo.svg @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/src/renderer/src/config/models/default.ts b/src/renderer/src/config/models/default.ts index 45fa7f79c4..f589fc24f6 100644 --- a/src/renderer/src/config/models/default.ts +++ b/src/renderer/src/config/models/default.ts @@ -1785,5 +1785,13 @@ export const SYSTEM_MODELS: Record = provider: 'cerebras', group: 'qwen' } + ], + mimo: [ + { + id: 'mimo-v2-flash', + name: 'Mimo V2 Flash', + provider: 'mimo', + group: 'Mimo' + } ] } diff --git a/src/renderer/src/config/models/logo.ts b/src/renderer/src/config/models/logo.ts index fe1a919c5e..75ad71f662 100644 --- a/src/renderer/src/config/models/logo.ts +++ b/src/renderer/src/config/models/logo.ts @@ -103,6 +103,7 @@ import MicrosoftModelLogo from '@renderer/assets/images/models/microsoft.png' import MicrosoftModelLogoDark from '@renderer/assets/images/models/microsoft_dark.png' import MidjourneyModelLogo from '@renderer/assets/images/models/midjourney.png' import MidjourneyModelLogoDark from '@renderer/assets/images/models/midjourney_dark.png' +import MiMoModelLogo from '@renderer/assets/images/models/mimo.svg' import { default as MinicpmModelLogo, default as MinicpmModelLogoDark @@ -301,7 +302,8 @@ export function getModelLogoById(modelId: string): string | undefined { bytedance: BytedanceModelLogo, ling: LingModelLogo, ring: LingModelLogo, - '(V_1|V_1_TURBO|V_2|V_2A|V_2_TURBO|DESCRIBE|UPSCALE)': IdeogramModelLogo + '(V_1|V_1_TURBO|V_2|V_2A|V_2_TURBO|DESCRIBE|UPSCALE)': IdeogramModelLogo, + mimo: MiMoModelLogo } as const satisfies Record for (const key in logoMap) { diff --git a/src/renderer/src/config/models/reasoning.ts b/src/renderer/src/config/models/reasoning.ts index a5e47ef3b1..498bad5eeb 100644 --- a/src/renderer/src/config/models/reasoning.ts +++ b/src/renderer/src/config/models/reasoning.ts @@ -52,6 +52,7 @@ export const MODEL_SUPPORTED_REASONING_EFFORT = { doubao_no_auto: ['high'] as const, doubao_after_251015: ['minimal', 'low', 'medium', 'high'] as const, hunyuan: ['auto'] as const, + mimo: ['auto'] as const, zhipu: ['auto'] as const, perplexity: ['low', 'medium', 'high'] as const, deepseek_hybrid: ['auto'] as const @@ -80,6 +81,7 @@ export const MODEL_SUPPORTED_OPTIONS: ThinkingOptionConfig = { doubao: ['none', ...MODEL_SUPPORTED_REASONING_EFFORT.doubao] as const, doubao_no_auto: ['none', ...MODEL_SUPPORTED_REASONING_EFFORT.doubao_no_auto] as const, doubao_after_251015: MODEL_SUPPORTED_REASONING_EFFORT.doubao_after_251015, + mimo: ['none', ...MODEL_SUPPORTED_REASONING_EFFORT.mimo] as const, hunyuan: ['none', ...MODEL_SUPPORTED_REASONING_EFFORT.hunyuan] as const, zhipu: ['none', ...MODEL_SUPPORTED_REASONING_EFFORT.zhipu] as const, perplexity: MODEL_SUPPORTED_REASONING_EFFORT.perplexity, @@ -155,6 +157,7 @@ const _getThinkModelType = (model: Model): ThinkingModelType => { else if (isSupportedReasoningEffortPerplexityModel(model)) thinkingModelType = 'perplexity' else if (isSupportedThinkingTokenZhipuModel(model)) thinkingModelType = 'zhipu' else if (isDeepSeekHybridInferenceModel(model)) thinkingModelType = 'deepseek_hybrid' + else if (isSupportedThinkingTokenMiMoModel(model)) thinkingModelType = 'mimo' return thinkingModelType } @@ -255,7 +258,8 @@ function _isSupportedThinkingTokenModel(model: Model): boolean { isSupportedThinkingTokenClaudeModel(model) || isSupportedThinkingTokenDoubaoModel(model) || isSupportedThinkingTokenHunyuanModel(model) || - isSupportedThinkingTokenZhipuModel(model) + isSupportedThinkingTokenZhipuModel(model) || + isSupportedThinkingTokenMiMoModel(model) ) } @@ -548,6 +552,11 @@ export const isSupportedThinkingTokenZhipuModel = (model: Model): boolean => { return ['glm-4.5', 'glm-4.6'].some((id) => modelId.includes(id)) } +export const isSupportedThinkingTokenMiMoModel = (model: Model): boolean => { + const modelId = getLowerBaseModelName(model.id, '/') + return ['mimo-v2-flash'].some((id) => modelId.includes(id)) +} + export const isDeepSeekHybridInferenceModel = (model: Model) => { const { idResult, nameResult } = withModelIdAndNameAsId(model, (model) => { const modelId = getLowerBaseModelName(model.id) @@ -586,6 +595,8 @@ export const isZhipuReasoningModel = (model?: Model): boolean => { return isSupportedThinkingTokenZhipuModel(model) || modelId.includes('glm-z1') } +export const isMiMoReasoningModel = isSupportedThinkingTokenMiMoModel + export const isStepReasoningModel = (model?: Model): boolean => { if (!model) { return false @@ -636,6 +647,7 @@ export function isReasoningModel(model?: Model): boolean { isDeepSeekHybridInferenceModel(model) || isLingReasoningModel(model) || isMiniMaxReasoningModel(model) || + isMiMoReasoningModel(model) || modelId.includes('magistral') || modelId.includes('pangu-pro-moe') || modelId.includes('seed-oss') || diff --git a/src/renderer/src/config/providers.ts b/src/renderer/src/config/providers.ts index bc32ef3490..5d64991fdb 100644 --- a/src/renderer/src/config/providers.ts +++ b/src/renderer/src/config/providers.ts @@ -31,6 +31,7 @@ import JinaProviderLogo from '@renderer/assets/images/providers/jina.png' import LanyunProviderLogo from '@renderer/assets/images/providers/lanyun.png' import LMStudioProviderLogo from '@renderer/assets/images/providers/lmstudio.png' import LongCatProviderLogo from '@renderer/assets/images/providers/longcat.png' +import MiMoProviderLogo from '@renderer/assets/images/providers/mimo.svg' import MinimaxProviderLogo from '@renderer/assets/images/providers/minimax.png' import MistralProviderLogo from '@renderer/assets/images/providers/mistral.png' import ModelScopeProviderLogo from '@renderer/assets/images/providers/modelscope.png' @@ -695,6 +696,17 @@ export const SYSTEM_PROVIDERS_CONFIG: Record = models: SYSTEM_MODELS.cerebras, isSystem: true, enabled: false + }, + mimo: { + id: 'mimo', + name: 'Xiaomi MiMo', + type: 'openai', + apiKey: '', + apiHost: 'https://api.xiaomimimo.com', + anthropicApiHost: 'https://api.xiaomimimo.com/anthropic', + models: SYSTEM_MODELS.mimo, + isSystem: true, + enabled: false } } as const @@ -763,7 +775,8 @@ export const PROVIDER_LOGO_MAP: AtLeast = { huggingface: HuggingfaceProviderLogo, sophnet: SophnetProviderLogo, gateway: AIGatewayProviderLogo, - cerebras: CerebrasProviderLogo + cerebras: CerebrasProviderLogo, + mimo: MiMoProviderLogo } as const export function getProviderLogo(providerId: string) { @@ -1434,5 +1447,16 @@ export const PROVIDER_URLS: Record = { docs: 'https://inference-docs.cerebras.ai/introduction', models: 'https://inference-docs.cerebras.ai/models/overview' } + }, + mimo: { + api: { + url: 'https://api.xiaomimimo.com/v1' + }, + websites: { + official: 'https://platform.xiaomimimo.com/', + apiKey: 'https://platform.xiaomimimo.com/#/console/usage', + docs: 'https://platform.xiaomimimo.com/#/docs/welcome', + models: 'https://platform.xiaomimimo.com/' + } } } diff --git a/src/renderer/src/i18n/label.ts b/src/renderer/src/i18n/label.ts index 2830267088..19ea70867a 100644 --- a/src/renderer/src/i18n/label.ts +++ b/src/renderer/src/i18n/label.ts @@ -88,7 +88,8 @@ const providerKeyMap = { huggingface: 'provider.huggingface', sophnet: 'provider.sophnet', gateway: 'provider.ai-gateway', - cerebras: 'provider.cerebras' + cerebras: 'provider.cerebras', + mimo: 'provider.mimo' } as const /** diff --git a/src/renderer/src/store/index.ts b/src/renderer/src/store/index.ts index 7eb762afd8..535e82a6ee 100644 --- a/src/renderer/src/store/index.ts +++ b/src/renderer/src/store/index.ts @@ -67,7 +67,7 @@ const persistedReducer = persistReducer( { key: 'cherry-studio', storage, - version: 184, + version: 185, blacklist: ['runtime', 'messages', 'messageBlocks', 'tabs', 'toolPermissions'], migrate }, diff --git a/src/renderer/src/store/migrate.ts b/src/renderer/src/store/migrate.ts index 0a1f8ea70d..67028442fe 100644 --- a/src/renderer/src/store/migrate.ts +++ b/src/renderer/src/store/migrate.ts @@ -3017,6 +3017,16 @@ const migrateConfig = { logger.error('migrate 184 error', error as Error) return state } + }, + '185': (state: RootState) => { + try { + addProvider(state, 'mimo') + logger.info('migrate 185 success') + return state + } catch (error) { + logger.error('migrate 185 error', error as Error) + return state + } } } diff --git a/src/renderer/src/types/index.ts b/src/renderer/src/types/index.ts index 197d217793..d024847a48 100644 --- a/src/renderer/src/types/index.ts +++ b/src/renderer/src/types/index.ts @@ -102,6 +102,7 @@ const ThinkModelTypes = [ 'doubao', 'doubao_no_auto', 'doubao_after_251015', + 'mimo', 'hunyuan', 'zhipu', 'perplexity', diff --git a/src/renderer/src/types/provider.ts b/src/renderer/src/types/provider.ts index 4e3e34760c..edab3a7305 100644 --- a/src/renderer/src/types/provider.ts +++ b/src/renderer/src/types/provider.ts @@ -189,7 +189,8 @@ export const SystemProviderIdSchema = z.enum([ 'huggingface', 'sophnet', 'gateway', - 'cerebras' + 'cerebras', + 'mimo' ]) export type SystemProviderId = z.infer @@ -258,7 +259,8 @@ export const SystemProviderIds = { longcat: 'longcat', huggingface: 'huggingface', gateway: 'gateway', - cerebras: 'cerebras' + cerebras: 'cerebras', + mimo: 'mimo' } as const satisfies Record type SystemProviderIdTypeMap = typeof SystemProviderIds