Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions apps/desktop/src/main/ai/auth/resolver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -331,6 +331,7 @@ const BUILTIN_TO_SUPPORTED: Record<string, SupportedProvider> = {
xai: 'xai',
openrouter: 'openrouter',
zai: 'zai',
minimax: 'minimax',
ollama: 'ollama',
};

Expand Down
2 changes: 2 additions & 0 deletions apps/desktop/src/main/ai/auth/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ export const PROVIDER_ENV_VARS: Record<SupportedProvider, string | undefined> =
xai: 'XAI_API_KEY',
openrouter: 'OPENROUTER_API_KEY',
zai: 'ZHIPU_API_KEY',
minimax: 'MINIMAX_API_KEY',
ollama: undefined, // No auth required for local Ollama
} as const;

Expand All @@ -96,6 +97,7 @@ export const PROVIDER_SETTINGS_KEY: Partial<Record<SupportedProvider, string>> =
azure: 'globalAzureApiKey',
openrouter: 'globalOpenRouterApiKey',
zai: 'globalZAIApiKey',
minimax: 'globalMiniMaxApiKey',
} as const;

/**
Expand Down
1 change: 1 addition & 0 deletions apps/desktop/src/main/ai/config/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,7 @@ export const MODEL_PROVIDER_MAP: Record<string, SupportedProvider> = {
'llama-': 'groq',
'grok-': 'xai',
'glm-': 'zai',
'minimax-': 'minimax',
} as const;

// ============================================
Expand Down
6 changes: 6 additions & 0 deletions apps/desktop/src/main/ai/providers/__tests__/factory.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,12 @@ describe('detectProviderFromModel', () => {
expect(detectProviderFromModel('grok-2')).toBe('xai');
});

it('detects MiniMax from minimax- prefix', () => {
expect(detectProviderFromModel('minimax-m2.7')).toBe('minimax');
expect(detectProviderFromModel('minimax-m2.7-highspeed')).toBe('minimax');
expect(detectProviderFromModel('minimax-m2.5')).toBe('minimax');
});

it('returns undefined for unknown model', () => {
expect(detectProviderFromModel('unknown-model')).toBeUndefined();
});
Expand Down
8 changes: 8 additions & 0 deletions apps/desktop/src/main/ai/providers/factory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,14 @@ function createProviderInstance(config: ProviderConfig) {
headers,
});

case SupportedProvider.MiniMax:
return createOpenAICompatible({
name: 'minimax',
apiKey,
baseURL: baseURL ?? 'https://api.minimax.io/v1',
headers,
});
Comment on lines +144 to +150
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

This logic for creating the MiniMax provider is duplicated in apps/desktop/src/main/ai/providers/registry.ts. To improve maintainability and avoid future inconsistencies, consider extracting this logic into a shared helper function. This pattern of duplication also exists for other createOpenAICompatible providers like ZAI.


case SupportedProvider.Ollama: {
// Account settings store the base Ollama URL (e.g., 'http://localhost:11434')
// but the OpenAI-compatible SDK needs the /v1 path appended.
Expand Down
8 changes: 8 additions & 0 deletions apps/desktop/src/main/ai/providers/registry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,14 @@ function createProviderSDKInstance(
headers,
});

case SupportedProvider.MiniMax:
return createOpenAICompatible({
name: 'minimax',
apiKey,
baseURL: baseURL ?? 'https://api.minimax.io/v1',
headers,
});

case SupportedProvider.Ollama: {
// Account settings store the base Ollama URL (e.g., 'http://localhost:11434')
// but the OpenAI-compatible SDK needs the /v1 path appended.
Expand Down
1 change: 1 addition & 0 deletions apps/desktop/src/main/ai/providers/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ export const SupportedProvider = {
XAI: 'xai',
OpenRouter: 'openrouter',
ZAI: 'zai',
MiniMax: 'minimax',
Ollama: 'ollama',
} as const;

Expand Down
33 changes: 33 additions & 0 deletions apps/desktop/src/shared/constants/models.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,11 @@ export const ALL_AVAILABLE_MODELS: ModelOption[] = [
{ value: 'grok-4-0709', label: 'Grok 4', provider: 'xai', description: 'Flagship', capabilities: { thinking: true, tools: true, vision: true, contextWindow: 256000 } },
{ value: 'grok-3', label: 'Grok 3', provider: 'xai', description: 'Text', capabilities: { thinking: false, tools: true, vision: false, contextWindow: 131072 } },
{ value: 'grok-3-mini', label: 'Grok 3 Mini', provider: 'xai', description: 'Fast reasoning', capabilities: { thinking: true, tools: true, vision: false, contextWindow: 131072 } },
// MiniMax
{ value: 'minimax-m2.7', label: 'MiniMax M2.7', provider: 'minimax', description: 'Latest flagship model with enhanced reasoning and coding', capabilities: { thinking: false, tools: true, vision: false, contextWindow: 204800 } },
{ value: 'minimax-m2.7-highspeed', label: 'MiniMax M2.7 High Speed', provider: 'minimax', description: 'High-speed version of M2.7 for low-latency scenarios', capabilities: { thinking: false, tools: true, vision: false, contextWindow: 204800 } },
{ value: 'minimax-m2.5', label: 'MiniMax M2.5', provider: 'minimax', description: 'Previous generation', capabilities: { thinking: false, tools: true, vision: false, contextWindow: 204800 } },
{ value: 'minimax-m2.5-highspeed', label: 'MiniMax M2.5 High Speed', provider: 'minimax', description: 'Fast and agile', capabilities: { thinking: false, tools: true, vision: false, contextWindow: 204800 } },
// Z.AI (Zhipu)
{ value: 'glm-5', label: 'GLM-5', provider: 'zai', description: 'Flagship', capabilities: { thinking: false, tools: true, vision: false, contextWindow: 128000 } },
{ value: 'glm-4.7', label: 'GLM-4.7', provider: 'zai', description: 'Previous flagship', capabilities: { thinking: false, tools: true, vision: false, contextWindow: 128000 } },
Expand Down Expand Up @@ -316,6 +321,11 @@ export const PROVIDER_PRESET_DEFINITIONS: Partial<Record<BuiltinProvider, Record
balanced: { primaryModel: 'glm-4.7', primaryThinking: 'low', phaseModels: { spec: 'glm-4.7', planning: 'glm-4.7', coding: 'glm-4.7', qa: 'glm-4.7' }, phaseThinking: { spec: 'low', planning: 'low', coding: 'low', qa: 'low' } },
quick: { primaryModel: 'glm-4.5-flash', primaryThinking: 'low', phaseModels: { spec: 'glm-4.5-flash', planning: 'glm-4.5-flash', coding: 'glm-4.5-flash', qa: 'glm-4.5-flash' }, phaseThinking: { spec: 'low', planning: 'low', coding: 'low', qa: 'low' } },
},
minimax: {
auto: { primaryModel: 'minimax-m2.7', primaryThinking: 'low', phaseModels: { spec: 'minimax-m2.7', planning: 'minimax-m2.7', coding: 'minimax-m2.7', qa: 'minimax-m2.7' }, phaseThinking: { spec: 'low', planning: 'low', coding: 'low', qa: 'low' } },
balanced: { primaryModel: 'minimax-m2.7', primaryThinking: 'low', phaseModels: { spec: 'minimax-m2.7', planning: 'minimax-m2.7', coding: 'minimax-m2.7', qa: 'minimax-m2.7' }, phaseThinking: { spec: 'low', planning: 'low', coding: 'low', qa: 'low' } },
quick: { primaryModel: 'minimax-m2.7-highspeed', primaryThinking: 'low', phaseModels: { spec: 'minimax-m2.7-highspeed', planning: 'minimax-m2.7-highspeed', coding: 'minimax-m2.7-highspeed', qa: 'minimax-m2.7-highspeed' }, phaseThinking: { spec: 'low', planning: 'low', coding: 'low', qa: 'low' } },
},
Comment on lines +324 to +328
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug: The MiniMax provider is missing the complex preset, causing the 'Complex Tasks' profile to silently fall back to the 'Auto' profile's settings.
Severity: MEDIUM

Suggested Fix

Add a complex preset to the minimax provider object within PROVIDER_PRESET_DEFINITIONS. This new preset should likely use the same model as the auto preset, such as minimax-m2.5, to align with the pattern used by other providers with limited model variety.

Prompt for AI Agent
Review the code at the location below. A potential bug has been identified by an AI
agent.
Verify if this is a real issue. If it is, propose a fix; if not, explain why it's not
valid.

Location: apps/desktop/src/shared/constants/models.ts#L322-L326

Potential issue: The MiniMax provider definition in `PROVIDER_PRESET_DEFINITIONS` is
missing a `complex` preset. When a user selects the 'Complex Tasks' profile, which has
an ID of 'complex', the `getProviderPresetOrFallback` function fails to find an exact
match for `minimax.complex`. The function then silently falls back to the `minimax.auto`
preset. This results in the 'Complex Tasks' profile behaving identically to the 'Auto'
profile for the MiniMax provider, ignoring the user's selection without any warning or
indication.

ollama: {
auto: { primaryModel: '', primaryThinking: 'low', phaseModels: { spec: '', planning: '', coding: '', qa: '' }, phaseThinking: { spec: 'low', planning: 'low', coding: 'low', qa: 'low' } },
complex: { primaryModel: '', primaryThinking: 'low', phaseModels: { spec: '', planning: '', coding: '', qa: '' }, phaseThinking: { spec: 'low', planning: 'low', coding: 'low', qa: 'low' } },
Expand Down Expand Up @@ -414,6 +424,27 @@ export const DEFAULT_MODEL_EQUIVALENCES: Record<string, Partial<Record<BuiltinPr
mistral: { modelId: 'mistral-large-latest', reasoning: { type: 'none' } },
groq: { modelId: 'meta-llama/llama-4-maverick', reasoning: { type: 'none' } },
zai: { modelId: 'glm-5', reasoning: { type: 'none' } },
minimax: { modelId: 'minimax-m2.7', reasoning: { type: 'none' } },
},
'minimax-m2.7': {
minimax: { modelId: 'minimax-m2.7', reasoning: { type: 'none' } },
anthropic: { modelId: 'claude-opus-4-6', reasoning: { type: 'adaptive_effort', level: 'high' } },
openai: { modelId: 'gpt-5.3-codex', reasoning: { type: 'reasoning_effort', level: 'high' } },
},
'minimax-m2.7-highspeed': {
minimax: { modelId: 'minimax-m2.7-highspeed', reasoning: { type: 'none' } },
anthropic: { modelId: 'claude-haiku-4-5-20251001', reasoning: { type: 'none' } },
openai: { modelId: 'gpt-5.1-codex-mini', reasoning: { type: 'reasoning_effort', level: 'low' } },
},
'minimax-m2.5': {
minimax: { modelId: 'minimax-m2.5', reasoning: { type: 'none' } },
anthropic: { modelId: 'claude-sonnet-4-6', reasoning: { type: 'thinking_tokens', level: 'medium' } },
openai: { modelId: 'gpt-5.2', reasoning: { type: 'reasoning_effort', level: 'medium' } },
},
'minimax-m2.5-highspeed': {
minimax: { modelId: 'minimax-m2.5-highspeed', reasoning: { type: 'none' } },
anthropic: { modelId: 'claude-haiku-4-5-20251001', reasoning: { type: 'none' } },
openai: { modelId: 'gpt-5.1-codex-mini', reasoning: { type: 'reasoning_effort', level: 'low' } },
},
'glm-5': {
zai: { modelId: 'glm-5', reasoning: { type: 'none' } },
Expand Down Expand Up @@ -443,6 +474,7 @@ export const DEFAULT_MODEL_EQUIVALENCES: Record<string, Partial<Record<BuiltinPr
groq: { modelId: 'llama-3.3-70b-versatile', reasoning: { type: 'none' } },
xai: { modelId: 'grok-3-mini', reasoning: { type: 'reasoning_effort', level: 'medium' } },
zai: { modelId: 'glm-4.7', reasoning: { type: 'none' } },
minimax: { modelId: 'minimax-m2.7', reasoning: { type: 'none' } },
},
'haiku': {
anthropic: { modelId: 'claude-haiku-4-5-20251001', reasoning: { type: 'none' } },
Expand All @@ -451,6 +483,7 @@ export const DEFAULT_MODEL_EQUIVALENCES: Record<string, Partial<Record<BuiltinPr
mistral: { modelId: 'mistral-small-latest', reasoning: { type: 'none' } },
groq: { modelId: 'llama-3.3-70b-versatile', reasoning: { type: 'none' } },
zai: { modelId: 'glm-4.5-flash', reasoning: { type: 'none' } },
minimax: { modelId: 'minimax-m2.7-highspeed', reasoning: { type: 'none' } },
},
// ── OpenAI models ─────────────────────────────────────────────────────────
'gpt-5.3-codex': {
Expand Down
6 changes: 6 additions & 0 deletions apps/desktop/src/shared/constants/providers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,12 @@ export const PROVIDER_REGISTRY: ProviderInfo[] = [
authMethods: ['api-key'], envVars: ['AZURE_OPENAI_API_KEY'],
configFields: ['baseUrl'],
},
{
id: 'minimax', name: 'MiniMax', description: 'MiniMax M2.7, M2.7-highspeed and M2.5 models',
category: 'popular',
authMethods: ['api-key'], envVars: ['MINIMAX_API_KEY'],
configFields: ['baseUrl'], website: 'https://platform.minimax.io',
},
Comment on lines +65 to +69
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Provider description omits minimax-m2.5-highspeed.

Line 65 is missing one currently supported MiniMax model, which makes the UI description inconsistent with the model catalog.

✏️ Suggested text fix
-    id: 'minimax', name: 'MiniMax', description: 'MiniMax M2.7, M2.7-highspeed and M2.5 models',
+    id: 'minimax', name: 'MiniMax', description: 'MiniMax M2.7, M2.7-highspeed, M2.5, and M2.5-highspeed models',
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
id: 'minimax', name: 'MiniMax', description: 'MiniMax M2.7, M2.7-highspeed and M2.5 models',
category: 'popular',
authMethods: ['api-key'], envVars: ['MINIMAX_API_KEY'],
configFields: ['baseUrl'], website: 'https://platform.minimax.io',
},
id: 'minimax', name: 'MiniMax', description: 'MiniMax M2.7, M2.7-highspeed, M2.5, and M2.5-highspeed models',
category: 'popular',
authMethods: ['api-key'], envVars: ['MINIMAX_API_KEY'],
configFields: ['baseUrl'], website: 'https://platform.minimax.io',
},
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/desktop/src/shared/constants/providers.ts` around lines 65 - 69, Update
the provider entry with id 'minimax' by editing its description field to include
the missing "minimax-m2.5-highspeed" model name so the text lists "MiniMax M2.7,
M2.7-highspeed, minimax-m2.5-highspeed and M2.5" (or otherwise include that
model) to match the model catalog; locate the object with id: 'minimax' and
adjust the description string accordingly.

{
id: 'ollama', name: 'Ollama', description: 'Local open-source models',
category: 'local',
Expand Down
2 changes: 1 addition & 1 deletion apps/desktop/src/shared/types/provider-account.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ export type CredentialSource = 'oauth' | 'api-key' | 'env' | 'keychain';
export type BuiltinProvider =
| 'anthropic' | 'openai' | 'google' | 'amazon-bedrock' | 'azure'
| 'mistral' | 'groq' | 'xai' | 'openrouter' | 'zai'
| 'ollama' | 'openai-compatible';
| 'minimax' | 'ollama' | 'openai-compatible';

export type BillingModel = 'subscription' | 'pay-per-use';

Comment on lines 7 to 13
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug: The BUILTIN_TO_SUPPORTED map in resolver.ts is missing an entry for 'minimax', causing MiniMax accounts to be silently skipped during queue-based provider routing.
Severity: CRITICAL

Suggested Fix

Add the missing 'minimax': 'minimax' entry to the BUILTIN_TO_SUPPORTED map located in apps/desktop/src/main/ai/auth/resolver.ts to ensure the provider is correctly resolved during queue-based routing.

Prompt for AI Agent
Review the code at the location below. A potential bug has been identified by an AI
agent.
Verify if this is a real issue. If it is, propose a fix; if not, explain why it's not
valid.

Location: apps/desktop/src/shared/types/provider-account.ts#L7-L13

Potential issue: The new 'minimax' provider is added to the `BuiltinProvider` type, but
the `BUILTIN_TO_SUPPORTED` map in `resolver.ts` was not updated. The
`resolveAuthFromQueue()` function uses this map to route requests. When it encounters a
'minimax' account, the lookup `BUILTIN_TO_SUPPORTED['minimax']` returns `undefined`,
causing the function to silently `continue` and skip the account. This effectively
disables the MiniMax provider for any multi-provider queue-based routing, which is the
primary routing mechanism in the application, rendering the integration non-functional
for its main use case.

Did we get this right? 👍 / 👎 to inform future reviews.

Expand Down
2 changes: 2 additions & 0 deletions apps/desktop/src/shared/types/settings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -284,6 +284,8 @@ export interface AppSettings {
globalAzureApiKey?: string;
globalAzureBaseUrl?: string;
globalBedrockRegion?: string;
globalZAIApiKey?: string;
globalMiniMaxApiKey?: string;
Comment on lines +287 to +288
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick | 🔵 Trivial

Add new API key fields to DEFAULT_APP_SETTINGS for consistency.

The new globalZAIApiKey and globalMiniMaxApiKey fields are correctly added as optional. However, DEFAULT_APP_SETTINGS in apps/desktop/src/shared/constants/config.ts (around line 51) initializes globalOpenAIApiKey but not these new keys. For consistency with other global API key fields, add explicit undefined initializers:

// In apps/desktop/src/shared/constants/config.ts DEFAULT_APP_SETTINGS:
globalZAIApiKey: undefined as string | undefined,
globalMiniMaxApiKey: undefined as string | undefined,

This ensures consistent initialization across settings resets and first-launch scenarios.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/desktop/src/shared/types/settings.ts` around lines 287 - 288,
DEFAULT_APP_SETTINGS is missing initializers for the newly added optional fields
globalZAIApiKey and globalMiniMaxApiKey; update the DEFAULT_APP_SETTINGS object
(same area that currently sets globalOpenAIApiKey) to include explicit
initializers for these two keys (set them to undefined with the same typed form
used elsewhere, e.g., as string | undefined) so they are consistently present
during resets and first-run initialization.

// Unified provider accounts (multi-provider)
providerAccounts?: ProviderAccount[];
/** Global priority order — array of ProviderAccount IDs. First = highest priority. */
Expand Down