feat: add MiniMax provider support via OpenAI-compatible endpoint

Register MiniMax as an OpenAI-compatible provider using the official
API at https://api.minimax.io/v1 with MiniMax-M2.5 as default model.

Changes across config, factory, migration, defaults, and docs.
This commit is contained in:
rfschubert 2026-02-22 08:08:41 -03:00 committed by rfshubert
parent 74b5af9e53
commit 80cbd2e663
7 changed files with 40 additions and 3 deletions

View file

@ -924,6 +924,7 @@ The subagent has access to tools (message, web_search, etc.) and can communicate
| `qwen` | LLM (Qwen direct) | [dashscope.console.aliyun.com](https://dashscope.console.aliyun.com) | | `qwen` | LLM (Qwen direct) | [dashscope.console.aliyun.com](https://dashscope.console.aliyun.com) |
| `groq` | LLM + **Voice transcription** (Whisper) | [console.groq.com](https://console.groq.com) | | `groq` | LLM + **Voice transcription** (Whisper) | [console.groq.com](https://console.groq.com) |
| `cerebras` | LLM (Cerebras direct) | [cerebras.ai](https://cerebras.ai) | | `cerebras` | LLM (Cerebras direct) | [cerebras.ai](https://cerebras.ai) |
| `minimax` | LLM (MiniMax direct) | [platform.minimax.io](https://platform.minimax.io) |
### Model Configuration (model_list) ### Model Configuration (model_list)
@ -956,6 +957,7 @@ This design also enables **multi-agent support** with flexible provider selectio
| **Cerebras** | `cerebras/` | `https://api.cerebras.ai/v1` | OpenAI | [Get Key](https://cerebras.ai) | | **Cerebras** | `cerebras/` | `https://api.cerebras.ai/v1` | OpenAI | [Get Key](https://cerebras.ai) |
| **火山引擎** | `volcengine/` | `https://ark.cn-beijing.volces.com/api/v3` | OpenAI | [Get Key](https://console.volcengine.com) | | **火山引擎** | `volcengine/` | `https://ark.cn-beijing.volces.com/api/v3` | OpenAI | [Get Key](https://console.volcengine.com) |
| **神算云** | `shengsuanyun/` | `https://router.shengsuanyun.com/api/v1` | OpenAI | - | | **神算云** | `shengsuanyun/` | `https://router.shengsuanyun.com/api/v1` | OpenAI | - |
| **MiniMax** | `minimax/` | `https://api.minimax.io/v1` | OpenAI | [Get Key](https://platform.minimax.io) |
| **Antigravity** | `antigravity/` | Google Cloud | Custom | OAuth only | | **Antigravity** | `antigravity/` | Google Cloud | Custom | OAuth only |
| **GitHub Copilot** | `github-copilot/` | `localhost:4321` | gRPC | - | | **GitHub Copilot** | `github-copilot/` | `localhost:4321` | gRPC | - |

View file

@ -46,6 +46,12 @@
"model": "openai/gpt-5.2", "model": "openai/gpt-5.2",
"api_key": "sk-key2", "api_key": "sk-key2",
"api_base": "https://api2.example.com/v1" "api_base": "https://api2.example.com/v1"
},
{
"model_name": "minimax-m2.5",
"model": "minimax/MiniMax-M2.5",
"api_key": "sk-your-minimax-key",
"api_base": "https://api.minimax.io/v1"
} }
], ],
"channels": { "channels": {

View file

@ -432,6 +432,7 @@ type ProvidersConfig struct {
Qwen ProviderConfig `json:"qwen"` Qwen ProviderConfig `json:"qwen"`
Mistral ProviderConfig `json:"mistral"` Mistral ProviderConfig `json:"mistral"`
Avian ProviderConfig `json:"avian"` Avian ProviderConfig `json:"avian"`
Minimax ProviderConfig `json:"minimax"`
} }
// IsEmpty checks if all provider configs are empty (no API keys or API bases set) // IsEmpty checks if all provider configs are empty (no API keys or API bases set)
@ -456,7 +457,8 @@ func (p ProvidersConfig) IsEmpty() bool {
p.Antigravity.APIKey == "" && p.Antigravity.APIBase == "" && p.Antigravity.APIKey == "" && p.Antigravity.APIBase == "" &&
p.Qwen.APIKey == "" && p.Qwen.APIBase == "" && p.Qwen.APIKey == "" && p.Qwen.APIBase == "" &&
p.Mistral.APIKey == "" && p.Mistral.APIBase == "" && p.Mistral.APIKey == "" && p.Mistral.APIBase == "" &&
p.Avian.APIKey == "" && p.Avian.APIBase == "" p.Avian.APIKey == "" && p.Avian.APIBase == "" &&
p.Minimax.APIKey == "" && p.Minimax.APIBase == ""
} }
// MarshalJSON implements custom JSON marshaling for ProvidersConfig // MarshalJSON implements custom JSON marshaling for ProvidersConfig

View file

@ -277,6 +277,14 @@ func DefaultConfig() *Config {
APIKey: "", APIKey: "",
}, },
// MiniMax - https://platform.minimax.io/
{
ModelName: "minimax-m2.5",
Model: "minimax/MiniMax-M2.5",
APIBase: "https://api.minimax.io/v1",
APIKey: "",
},
// Antigravity (Google Cloud Code Assist) - OAuth only // Antigravity (Google Cloud Code Assist) - OAuth only
{ {
ModelName: "gemini-flash", ModelName: "gemini-flash",

View file

@ -390,6 +390,23 @@ func ConvertProvidersToModelList(cfg *Config) []ModelConfig {
}, true }, true
}, },
}, },
{
providerNames: []string{"minimax"},
protocol: "minimax",
buildConfig: func(p ProvidersConfig) (ModelConfig, bool) {
if p.Minimax.APIKey == "" && p.Minimax.APIBase == "" {
return ModelConfig{}, false
}
return ModelConfig{
ModelName: "minimax",
Model: "minimax/MiniMax-M2.5",
APIKey: p.Minimax.APIKey,
APIBase: p.Minimax.APIBase,
Proxy: p.Minimax.Proxy,
RequestTimeout: p.Minimax.RequestTimeout,
}, true
},
},
} }
// Process each provider migration // Process each provider migration

View file

@ -94,7 +94,7 @@ func CreateProviderFromConfig(cfg *config.ModelConfig) (LLMProvider, string, err
case "litellm", "openrouter", "groq", "zhipu", "gemini", "nvidia", case "litellm", "openrouter", "groq", "zhipu", "gemini", "nvidia",
"ollama", "moonshot", "shengsuanyun", "deepseek", "cerebras", "ollama", "moonshot", "shengsuanyun", "deepseek", "cerebras",
"volcengine", "vllm", "qwen", "mistral", "avian": "volcengine", "vllm", "qwen", "mistral", "avian", "minimax":
// All other OpenAI-compatible HTTP providers // All other OpenAI-compatible HTTP providers
if cfg.APIKey == "" && cfg.APIBase == "" { if cfg.APIKey == "" && cfg.APIBase == "" {
return nil, "", fmt.Errorf("api_key or api_base is required for HTTP-based protocol %q", protocol) return nil, "", fmt.Errorf("api_key or api_base is required for HTTP-based protocol %q", protocol)
@ -204,6 +204,8 @@ func getDefaultAPIBase(protocol string) string {
return "https://ark.cn-beijing.volces.com/api/v3" return "https://ark.cn-beijing.volces.com/api/v3"
case "qwen": case "qwen":
return "https://dashscope.aliyuncs.com/compatible-mode/v1" return "https://dashscope.aliyuncs.com/compatible-mode/v1"
case "minimax":
return "https://api.minimax.io/v1"
case "vllm": case "vllm":
return "http://localhost:8000/v1" return "http://localhost:8000/v1"
case "mistral": case "mistral":

View file

@ -363,7 +363,7 @@ func normalizeModel(model, apiBase string) string {
prefix := strings.ToLower(before) prefix := strings.ToLower(before)
switch prefix { switch prefix {
case "litellm", "moonshot", "nvidia", "groq", "ollama", "deepseek", "google", "openrouter", "zhipu", "mistral": case "litellm", "moonshot", "nvidia", "groq", "ollama", "deepseek", "google", "openrouter", "zhipu", "mistral", "minimax":
return after return after
default: default:
return model return model