Skip to content
64 changes: 64 additions & 0 deletions cli/src/config/schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,7 @@
"qwen-code",
"gemini-cli",
"zai",
"minimax",
"unbound",
"requesty",
"roo",
Expand Down Expand Up @@ -1207,6 +1208,27 @@
}
}
},
{
"if": {
"properties": { "provider": { "const": "minimax" } }
},
"then": {
"properties": {
"minimaxBaseUrl": {
"type": "string",
"description": "MiniMax base URL"
},
"minimaxApiKey": {
"type": "string",
"description": "MiniMax API key"
},
"apiModelId": {
"type": "string",
"description": "MiniMax model ID"
}
}
}
},
{
"if": {
"properties": { "provider": { "const": "doubao" } }
Expand Down Expand Up @@ -1294,6 +1316,48 @@
}
}
},
{
"if": {
"properties": {
"provider": { "const": "minimax" },
"minimaxBaseUrl": { "type": "string", "minLength": 1 }
},
"required": ["minimaxBaseUrl"]
},
"then": {
"properties": {
"minimaxBaseUrl": { "minLength": 1 }
}
}
},
{
"if": {
"properties": {
"provider": { "const": "minimax" },
"minimaxApiKey": { "type": "string", "minLength": 1 }
},
"required": ["minimaxApiKey"]
},
"then": {
"properties": {
"minimaxApiKey": { "minLength": 10 }
}
}
},
{
"if": {
"properties": {
"provider": { "const": "minimax" },
"apiModelId": { "type": "string", "minLength": 1 }
},
"required": ["apiModelId"]
},
"then": {
"properties": {
"apiModelId": { "minLength": 1 }
}
}
},
{
"if": {
"properties": { "provider": { "const": "chutes" } }
Expand Down
1 change: 1 addition & 0 deletions cli/src/constants/providers/__tests__/models.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ describe("Static Provider Models", () => {
"cerebras",
"sambanova",
"zai",
"minimax",
"fireworks",
"featherless",
"roo",
Expand Down
1 change: 1 addition & 0 deletions cli/src/constants/providers/labels.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ export const PROVIDER_LABELS: Record<ProviderName, string> = {
"qwen-code": "Qwen Code",
"gemini-cli": "Gemini CLI",
zai: "Zai",
minimax: "MiniMax",
unbound: "Unbound",
requesty: "Requesty",
roo: "Roo",
Expand Down
10 changes: 10 additions & 0 deletions cli/src/constants/providers/models.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ import {
claudeCodeDefaultModelId,
geminiCliModels,
geminiCliDefaultModelId,
minimaxModels,
minimaxDefaultModelId,
} from "@roo-code/types"

/**
Expand Down Expand Up @@ -117,6 +119,7 @@ export const PROVIDER_TO_ROUTER_NAME: Record<ProviderName, RouterName | null> =
moonshot: null,
deepseek: null,
doubao: null,
minimax: null,
"qwen-code": null,
"human-relay": null,
"fake-ai": null,
Expand Down Expand Up @@ -162,6 +165,7 @@ export const PROVIDER_MODEL_FIELD: Record<ProviderName, string | null> = {
moonshot: null,
deepseek: null,
doubao: null,
minimax: null,
"qwen-code": null,
"human-relay": null,
"fake-ai": null,
Expand Down Expand Up @@ -239,6 +243,7 @@ export const DEFAULT_MODEL_IDS: Partial<Record<ProviderName, string>> = {
sambanova: sambaNovaDefaultModelId,
featherless: featherlessDefaultModelId,
deepinfra: "deepseek-ai/DeepSeek-R1-0528",
minimax: "MiniMax-M2",
zai: internationalZAiDefaultModelId,
roo: rooDefaultModelId,
"gemini-cli": geminiCliDefaultModelId,
Expand Down Expand Up @@ -302,6 +307,11 @@ export function getModelsByProvider(params: {
models: moonshotModels as ModelRecord,
defaultModel: moonshotDefaultModelId,
}
case "minimax":
return {
models: minimaxModels as ModelRecord,
defaultModel: minimaxDefaultModelId,
}
case "deepseek":
return {
models: deepSeekModels as ModelRecord,
Expand Down
19 changes: 18 additions & 1 deletion cli/src/constants/providers/settings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -410,6 +410,18 @@ export const FIELD_REGISTRY: Record<string, FieldMetadata> = {
placeholder: "Enter API line...",
},

// Minimax fields
minimaxBaseUrl: {
label: "Base URL",
type: "text",
placeholder: "Enter MiniMax base URL...",
},
minimaxApiKey: {
label: "API Key",
type: "password",
placeholder: "Enter MiniMax API key...",
},

// Unbound fields
unboundApiKey: {
label: "API Key",
Expand Down Expand Up @@ -767,7 +779,11 @@ export const getProviderSettings = (provider: ProviderName, config: ProviderSett
type: "text",
},
]

case "minimax":
return [
createFieldConfig("minimaxBaseUrl", config, "https://api.minimax.io/anthropic"),
createFieldConfig("minimaxApiKey", config),
]
case "fake-ai":
return [
{
Expand Down Expand Up @@ -825,6 +841,7 @@ export const PROVIDER_DEFAULT_MODELS: Record<ProviderName, string> = {
"vercel-ai-gateway": "gpt-4o",
"virtual-quota-fallback": "gpt-4o",
"human-relay": "human",
minimax: "MiniMax-M2",
"fake-ai": "fake-model",
}

Expand Down
1 change: 1 addition & 0 deletions cli/src/constants/providers/validation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,4 +44,5 @@ export const PROVIDER_REQUIRED_FIELDS: Record<ProviderName, string[]> = {
vertex: [], // Has special validation logic (either/or fields)
"vscode-lm": [], // Has nested object validation
"virtual-quota-fallback": [], // Has array validation
minimax: ["minimaxBaseUrl", "minimaxApiKey", "apiModelId"],
}
2 changes: 1 addition & 1 deletion cli/src/services/logs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ export class LogsService {
stack: error.stack,
// Include any additional enumerable properties
...Object.getOwnPropertyNames(error)
.filter(key => key !== "message" && key !== "name" && key !== "stack")
.filter((key) => key !== "message" && key !== "name" && key !== "stack")
.reduce(
(acc, key) => {
acc[key] = (error as any)[key]
Expand Down
5 changes: 5 additions & 0 deletions cli/src/types/messages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ export type ProviderName =
| "io-intelligence"
| "roo"
| "vercel-ai-gateway"
| "minimax"

// Provider Settings Entry for profile metadata
export interface ProviderSettingsEntry {
Expand Down Expand Up @@ -320,6 +321,10 @@ export interface ProviderSettings {
vercelAiGatewayApiKey?: string
vercelAiGatewayModelId?: string

// MiniMax AI
minimaxBaseUrl?: "https://api.minimax.io/anthropic" | "https://api.minimaxi.com/anthropic"
minimaxApiKey?: string

// Allow additional fields for extensibility
[key: string]: any
}
Expand Down
1 change: 1 addition & 0 deletions packages/types/src/global-settings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,7 @@ export const SECRET_STATE_KEYS = [
"deepInfraApiKey",
"codeIndexOpenAiKey",
"codeIndexQdrantApiKey",
"minimaxApiKey",
// kilocode_change start
"kilocodeToken",
"syntheticApiKey",
Expand Down
17 changes: 17 additions & 0 deletions packages/types/src/provider-settings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import {
vscodeLlmModels,
xaiModels,
internationalZAiModels,
minimaxModels,
} from "./providers/index.js"
import { toolUseStylesSchema } from "./kilocode/native-function-calling.js"

Expand Down Expand Up @@ -141,6 +142,7 @@ export const providerNames = [
"groq",
"mistral",
"moonshot",
"minimax",
"openai-native",
"qwen-code",
"roo",
Expand Down Expand Up @@ -411,6 +413,13 @@ const sambaNovaSchema = apiModelIdProviderModelSchema.extend({
sambaNovaApiKey: z.string().optional(),
})

const minimaxSchema = apiModelIdProviderModelSchema.extend({
minimaxBaseUrl: z
.union([z.literal("https://api.minimax.io/anthropic"), z.literal("https://api.minimaxi.com/anthropic")])
.optional(),
minimaxApiKey: z.string().optional(),
})

// kilocode_change start
const ovhcloudSchema = baseProviderSettingsSchema.extend({
ovhCloudAiEndpointsApiKey: z.string().optional(),
Expand Down Expand Up @@ -518,6 +527,7 @@ export const providerSettingsSchemaDiscriminated = z.discriminatedUnion("apiProv
humanRelaySchema.merge(z.object({ apiProvider: z.literal("human-relay") })),
fakeAiSchema.merge(z.object({ apiProvider: z.literal("fake-ai") })),
xaiSchema.merge(z.object({ apiProvider: z.literal("xai") })),
minimaxSchema.merge(z.object({ apiProvider: z.literal("minimax") })),
// kilocode_change start
geminiCliSchema.merge(z.object({ apiProvider: z.literal("gemini-cli") })),
kilocodeSchema.merge(z.object({ apiProvider: z.literal("kilocode") })),
Expand Down Expand Up @@ -570,6 +580,7 @@ export const providerSettingsSchema = z.object({
...humanRelaySchema.shape,
...fakeAiSchema.shape,
...xaiSchema.shape,
...minimaxSchema.shape,
...groqSchema.shape,
...huggingFaceSchema.shape,
...chutesSchema.shape,
Expand Down Expand Up @@ -660,6 +671,7 @@ export const modelIdKeysByProvider: Record<TypicalProvider, ModelIdKey> = {
unbound: "unboundModelId",
requesty: "requestyModelId",
xai: "apiModelId",
minimax: "apiModelId",
groq: "apiModelId",
chutes: "apiModelId",
litellm: "litellmModelId",
Expand Down Expand Up @@ -799,6 +811,11 @@ export const MODELS_BY_PROVIDER: Record<
},
xai: { id: "xai", label: "xAI (Grok)", models: Object.keys(xaiModels) },
zai: { id: "zai", label: "Zai", models: Object.keys(internationalZAiModels) },
minimax: {
id: "minimax",
label: "MiniMax",
models: Object.keys(minimaxModels),
},

// Dynamic providers; models pulled from remote APIs.
glama: { id: "glama", label: "Glama", models: [] },
Expand Down
1 change: 1 addition & 0 deletions packages/types/src/providers/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,3 +35,4 @@ export * from "./xai.js"
export * from "./vercel-ai-gateway.js"
export * from "./zai.js"
export * from "./deepinfra.js"
export * from "./minimax.js"
23 changes: 23 additions & 0 deletions packages/types/src/providers/minimax.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import type { ModelInfo } from "../model.js"

// Minimax
// https://www.minimax.io/platform/document/text_api_intro
// https://www.minimax.io/platform/document/pricing
export type MinimaxModelId = keyof typeof minimaxModels
export const minimaxDefaultModelId: MinimaxModelId = "MiniMax-M2"

export const minimaxModels = {
"MiniMax-M2": {
maxTokens: 128_000,
contextWindow: 192_000,
supportsImages: false,
supportsPromptCache: false,
inputPrice: 0.3,
outputPrice: 1.2,
cacheWritesPrice: 0,
cacheReadsPrice: 0,
},
} as const satisfies Record<string, ModelInfo>

export const MINIMAX_DEFAULT_TEMPERATURE = 1.0
export const MINIMAX_DEFAULT_MAX_TOKENS = 16384
3 changes: 3 additions & 0 deletions src/api/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ import {
DoubaoHandler,
ZAiHandler,
FireworksHandler,
MiniMaxHandler,
SyntheticHandler, // kilocode_change
RooHandler,
FeatherlessHandler,
Expand Down Expand Up @@ -202,6 +203,8 @@ export function buildApiHandler(configuration: ProviderSettings): ApiHandler {
return new FeatherlessHandler(options)
case "vercel-ai-gateway":
return new VercelAiGatewayHandler(options)
case "minimax":
return new MiniMaxHandler(options)
// kilocode_change start
case "ovhcloud":
return new OVHcloudAIEndpointsHandler(options)
Expand Down
Loading