diff --git a/backend/core/config.py b/backend/core/config.py
index a24f3f05..3d8a3a67 100644
--- a/backend/core/config.py
+++ b/backend/core/config.py
@@ -420,6 +420,7 @@ def get_default_llm_model_for_provider(provider: Optional[str]) -> str:
- 百炼(aliyun):默认 deepseek-v3.2(兼容模式)
- DeepSeek:默认 deepseek-chat
- Moonshot:默认 moonshot-v1-8k
+ - MiniMax: MiniMax-M3 by default
- 其他/未知:回退到 DEFAULT_LLM_MODEL
"""
p = (provider or "").strip().lower() or DEFAULT_LLM_PROVIDER
@@ -429,4 +430,6 @@ def get_default_llm_model_for_provider(provider: Optional[str]) -> str:
return "deepseek-chat"
if p == "moonshot":
return "moonshot-v1-8k"
- return DEFAULT_LLM_MODEL
\ No newline at end of file
+ if p == "minimax":
+ return "MiniMax-M3"
+ return DEFAULT_LLM_MODEL
diff --git a/backend/core/content.py b/backend/core/content.py
index 4ed8e541..f8d1a607 100644
--- a/backend/core/content.py
+++ b/backend/core/content.py
@@ -86,6 +86,13 @@ def _extract_llm_base_url(ctx) -> str | None:
"kimi-k2-turbo-preview": {"name": "Kimi K2 Turbo", "max_tokens": 1024},
},
},
+ "minimax": {
+ "base_url": "https://api.minimax.io/v1",
+ "models": {
+ "MiniMax-M3": {"name": "MiniMax-M3", "max_tokens": 1024},
+ "MiniMax-M2.7": {"name": "MiniMax-M2.7", "max_tokens": 1024},
+ },
+ },
# Custom OpenAI-compatible provider: base_url must be provided at call-time.
"openai_compat": {
"base_url": "",
@@ -292,6 +299,7 @@ def _get_client(
"deepseek": "DEEPSEEK_API_KEY",
"aliyun": "DASHSCOPE_API_KEY",
"moonshot": "MOONSHOT_API_KEY",
+ "minimax": "MINIMAX_API_KEY",
}
env_key = api_key_map.get(provider, "DEEPSEEK_API_KEY")
api_key = os.getenv(env_key, "")
diff --git a/backend/core/schemas.py b/backend/core/schemas.py
index f5ce5feb..23880ab2 100644
--- a/backend/core/schemas.py
+++ b/backend/core/schemas.py
@@ -14,7 +14,7 @@
_MAC_RE = re.compile(r"^([0-9A-Fa-f]{2}:){5}[0-9A-Fa-f]{2}$")
# 允许的 LLM 提供商
-_VALID_PROVIDERS = {"deepseek", "aliyun", "moonshot"}
+_VALID_PROVIDERS = {"deepseek", "aliyun", "moonshot", "minimax"}
_VALID_IMAGE_PROVIDERS = {"aliyun"}
# 允许的语言选项
diff --git a/backend/tests/test_custom_mode_api_key_simple.py b/backend/tests/test_custom_mode_api_key_simple.py
index b88ad873..bb807170 100644
--- a/backend/tests/test_custom_mode_api_key_simple.py
+++ b/backend/tests/test_custom_mode_api_key_simple.py
@@ -41,6 +41,23 @@ def test_get_client_uses_env_var_when_api_key_is_none(self):
assert client is not None
assert max_tokens > 0
+ def test_get_client_uses_minimax_defaults(self):
+ """Test that MiniMax uses its preset base URL and environment key."""
+ env_api_key = "minimax-demo"
+
+ with (
+ patch.dict(os.environ, {"MINIMAX_API_KEY": env_api_key}, clear=False),
+ patch("core.content.AsyncOpenAI") as mock_openai,
+ ):
+ mock_openai.return_value = MagicMock()
+ client, max_tokens = _get_client("minimax", "MiniMax-M3", api_key=None)
+
+ assert client is mock_openai.return_value
+ assert max_tokens > 0
+ assert mock_openai.call_args is not None
+ assert mock_openai.call_args.kwargs.get("api_key") == env_api_key
+ assert mock_openai.call_args.kwargs.get("base_url") == "https://api.minimax.io/v1"
+
def test_get_client_raises_error_when_user_key_empty(self):
"""测试 _get_client 在用户配置的 api_key 为空时抛出错误"""
with (
@@ -178,4 +195,3 @@ def test_none_key_flow(self):
with patch.dict(os.environ, {"DEEPSEEK_API_KEY": env_api_key}, clear=False):
client, max_tokens = _get_client("deepseek", "deepseek-chat", api_key=device_api_key)
assert client is not None
-
diff --git a/backend/tests/test_unit_config_store.py b/backend/tests/test_unit_config_store.py
index 816a6124..a4f54926 100644
--- a/backend/tests/test_unit_config_store.py
+++ b/backend/tests/test_unit_config_store.py
@@ -15,6 +15,7 @@
get_or_create_claim_token,
remove_mode_from_all_configs,
)
+from core.config import get_default_llm_model_for_provider
@pytest.fixture(autouse=True)
@@ -202,3 +203,6 @@ async def test_remove_mode_from_all_configs_cleans_modes_and_overrides(self):
assert "STOIC" in config["modes"]
assert "CUSTOM_DELETED" not in config["mode_overrides"]
assert config["mode_overrides"]["STOIC"]["city"] == "杭州"
+
+ def test_get_default_llm_model_for_provider_minimax(self):
+ assert get_default_llm_model_for_provider("minimax") == "MiniMax-M3"
diff --git a/backend/tests/test_unit_schemas.py b/backend/tests/test_unit_schemas.py
index 6221e4e7..b94ba7e6 100644
--- a/backend/tests/test_unit_schemas.py
+++ b/backend/tests/test_unit_schemas.py
@@ -72,6 +72,10 @@ def test_invalid_provider(self):
with pytest.raises(ValidationError, match="无效 LLM 提供商"):
ConfigRequest(mac="AA:BB:CC:DD:EE:FF", llmProvider="openai")
+ def test_minimax_provider_accepted(self):
+ body = ConfigRequest(mac="AA:BB:CC:DD:EE:FF", llmProvider="minimax")
+ assert body.llmProvider == "minimax"
+
def test_invalid_strategy(self):
with pytest.raises(ValidationError, match="无效刷新策略"):
ConfigRequest(mac="AA:BB:CC:DD:EE:FF", refreshStrategy="sequential")
diff --git a/webapp/app/[locale]/profile/page.tsx b/webapp/app/[locale]/profile/page.tsx
index b9141af2..833253ba 100644
--- a/webapp/app/[locale]/profile/page.tsx
+++ b/webapp/app/[locale]/profile/page.tsx
@@ -260,6 +260,9 @@ export default function ProfilePage() {
if (provider === "aliyun") {
return ["qwen3.5-flash", "deepseek-v3.2", "Moonshot-Kimi-K2-Instruct"];
}
+ if (provider === "minimax") {
+ return ["MiniMax-M3", "MiniMax-M2.7"];
+ }
// 默认 DeepSeek
return ["deepseek-chat", "deepseek-reasoner"];
};
@@ -630,6 +633,7 @@ export default function ProfilePage() {
>
+