refactor: merge minimax bundled plugins

This commit is contained in:
Peter Steinberger 2026-03-16 02:26:11 +00:00
parent 6513749ef6
commit 47a9c1a893
20 changed files with 258 additions and 273 deletions

View File

@ -16,6 +16,7 @@ Docs: https://docs.openclaw.ai
- Docs/Zalo: clarify the Marketplace-bot support matrix and config guidance so the Zalo channel docs match current Bot Creator behavior more closely. (#47552) Thanks @No898. - Docs/Zalo: clarify the Marketplace-bot support matrix and config guidance so the Zalo channel docs match current Bot Creator behavior more closely. (#47552) Thanks @No898.
- Install/update: allow package-manager installs from GitHub `main` via `openclaw update --tag main`, installer `--version main`, or direct npm/pnpm git specs. - Install/update: allow package-manager installs from GitHub `main` via `openclaw update --tag main`, installer `--version main`, or direct npm/pnpm git specs.
- Plugins/providers: move OpenRouter, GitHub Copilot, and OpenAI Codex provider/runtime logic into bundled plugins, including dynamic model fallback, runtime auth exchange, stream wrappers, capability hints, and cache-TTL policy. - Plugins/providers: move OpenRouter, GitHub Copilot, and OpenAI Codex provider/runtime logic into bundled plugins, including dynamic model fallback, runtime auth exchange, stream wrappers, capability hints, and cache-TTL policy.
- Plugins/MiniMax: merge the bundled MiniMax API and MiniMax OAuth plugin surfaces into a single default-on `minimax` plugin, while keeping legacy `minimax-portal-auth` config ids aliased for compatibility.
- Plugins/bundles: add compatible Codex, Claude, and Cursor bundle discovery/install support, map bundle skills into OpenClaw skills, and apply Claude bundle `settings.json` defaults to embedded Pi with shell overrides sanitized. - Plugins/bundles: add compatible Codex, Claude, and Cursor bundle discovery/install support, map bundle skills into OpenClaw skills, and apply Claude bundle `settings.json` defaults to embedded Pi with shell overrides sanitized.
- Plugins/agent integrations: broaden the plugin surface for app-server integrations with channel-aware commands, interactive callbacks, inbound claims, and Discord/Telegram conversation binding support. (#45318) Thanks @huntharo and @vincentkoc. - Plugins/agent integrations: broaden the plugin surface for app-server integrations with channel-aware commands, interactive callbacks, inbound claims, and Discord/Telegram conversation binding support. (#45318) Thanks @huntharo and @vincentkoc.

View File

@ -42,7 +42,7 @@ MiniMax highlights these improvements in M2.5:
Enable the bundled OAuth plugin and authenticate: Enable the bundled OAuth plugin and authenticate:
```bash ```bash
openclaw plugins enable minimax-portal-auth # skip if already loaded. openclaw plugins enable minimax # skip if already loaded.
openclaw gateway restart # restart if gateway is already running openclaw gateway restart # restart if gateway is already running
openclaw onboard --auth-choice minimax-portal openclaw onboard --auth-choice minimax-portal
``` ```
@ -52,7 +52,7 @@ You will be prompted to select an endpoint:
- **Global** - International users (`api.minimax.io`) - **Global** - International users (`api.minimax.io`)
- **CN** - Users in China (`api.minimaxi.com`) - **CN** - Users in China (`api.minimaxi.com`)
See [MiniMax OAuth plugin README](https://github.com/openclaw/openclaw/tree/main/extensions/minimax-portal-auth) for details. See [MiniMax plugin README](https://github.com/openclaw/openclaw/tree/main/extensions/minimax) for details.
### MiniMax M2.5 (API key) ### MiniMax M2.5 (API key)

View File

@ -172,8 +172,7 @@ Important trust note:
- Hugging Face provider catalog — bundled as `huggingface` (enabled by default) - Hugging Face provider catalog — bundled as `huggingface` (enabled by default)
- Kilo Gateway provider runtime — bundled as `kilocode` (enabled by default) - Kilo Gateway provider runtime — bundled as `kilocode` (enabled by default)
- Kimi Coding provider catalog — bundled as `kimi-coding` (enabled by default) - Kimi Coding provider catalog — bundled as `kimi-coding` (enabled by default)
- MiniMax provider catalog + usage — bundled as `minimax` (enabled by default) - MiniMax provider catalog + usage + OAuth — bundled as `minimax` (enabled by default; owns `minimax` and `minimax-portal`)
- MiniMax OAuth (provider auth + catalog) — bundled as `minimax-portal-auth` (enabled by default)
- Mistral provider capabilities — bundled as `mistral` (enabled by default) - Mistral provider capabilities — bundled as `mistral` (enabled by default)
- Model Studio provider catalog — bundled as `modelstudio` (enabled by default) - Model Studio provider catalog — bundled as `modelstudio` (enabled by default)
- Moonshot provider runtime — bundled as `moonshot` (enabled by default) - Moonshot provider runtime — bundled as `moonshot` (enabled by default)
@ -664,7 +663,7 @@ Default-on bundled plugin examples:
- `kilocode` - `kilocode`
- `kimi-coding` - `kimi-coding`
- `minimax` - `minimax`
- `minimax-portal-auth` - `minimax`
- `modelstudio` - `modelstudio`
- `moonshot` - `moonshot`
- `nvidia` - `nvidia`

View File

@ -1,33 +0,0 @@
# MiniMax OAuth (OpenClaw plugin)
OAuth provider plugin for **MiniMax** (OAuth).
## Enable
Bundled plugins are disabled by default. Enable this one:
```bash
openclaw plugins enable minimax-portal-auth
```
Restart the Gateway after enabling.
```bash
openclaw gateway restart
```
## Authenticate
```bash
openclaw models auth login --provider minimax-portal --set-default
```
You will be prompted to select an endpoint:
- **Global** - International users, optimized for overseas access (`api.minimax.io`)
- **China** - Optimized for users in China (`api.minimaxi.com`)
## Notes
- MiniMax OAuth uses a user-code login flow.
- Currently, OAuth login is supported only for the Coding plan

View File

@ -1,163 +0,0 @@
import {
buildOauthProviderAuthResult,
emptyPluginConfigSchema,
type OpenClawPluginApi,
type ProviderAuthContext,
type ProviderAuthResult,
type ProviderCatalogContext,
} from "openclaw/plugin-sdk/minimax-portal-auth";
import { ensureAuthProfileStore, listProfilesForProvider } from "../../src/agents/auth-profiles.js";
import { MINIMAX_OAUTH_MARKER } from "../../src/agents/model-auth-markers.js";
import { buildMinimaxPortalProvider } from "../../src/agents/models-config.providers.static.js";
import { loginMiniMaxPortalOAuth, type MiniMaxRegion } from "./oauth.js";
const PROVIDER_ID = "minimax-portal";
const PROVIDER_LABEL = "MiniMax";
const DEFAULT_MODEL = "MiniMax-M2.5";
const DEFAULT_BASE_URL_CN = "https://api.minimaxi.com/anthropic";
const DEFAULT_BASE_URL_GLOBAL = "https://api.minimax.io/anthropic";
function getDefaultBaseUrl(region: MiniMaxRegion): string {
return region === "cn" ? DEFAULT_BASE_URL_CN : DEFAULT_BASE_URL_GLOBAL;
}
function modelRef(modelId: string): string {
return `${PROVIDER_ID}/${modelId}`;
}
function buildProviderCatalog(params: { baseUrl: string; apiKey: string }) {
return {
...buildMinimaxPortalProvider(),
baseUrl: params.baseUrl,
apiKey: params.apiKey,
};
}
function resolveCatalog(ctx: ProviderCatalogContext) {
const explicitProvider = ctx.config.models?.providers?.[PROVIDER_ID];
const envApiKey = ctx.resolveProviderApiKey(PROVIDER_ID).apiKey;
const authStore = ensureAuthProfileStore(ctx.agentDir, {
allowKeychainPrompt: false,
});
const hasProfiles = listProfilesForProvider(authStore, PROVIDER_ID).length > 0;
const explicitApiKey =
typeof explicitProvider?.apiKey === "string" ? explicitProvider.apiKey.trim() : undefined;
const apiKey = envApiKey ?? explicitApiKey ?? (hasProfiles ? MINIMAX_OAUTH_MARKER : undefined);
if (!apiKey) {
return null;
}
const explicitBaseUrl =
typeof explicitProvider?.baseUrl === "string" ? explicitProvider.baseUrl.trim() : undefined;
return {
provider: buildProviderCatalog({
baseUrl: explicitBaseUrl || DEFAULT_BASE_URL_GLOBAL,
apiKey,
}),
};
}
function createOAuthHandler(region: MiniMaxRegion) {
const defaultBaseUrl = getDefaultBaseUrl(region);
const regionLabel = region === "cn" ? "CN" : "Global";
return async (ctx: ProviderAuthContext): Promise<ProviderAuthResult> => {
const progress = ctx.prompter.progress(`Starting MiniMax OAuth (${regionLabel})…`);
try {
const result = await loginMiniMaxPortalOAuth({
openUrl: ctx.openUrl,
note: ctx.prompter.note,
progress,
region,
});
progress.stop("MiniMax OAuth complete");
if (result.notification_message) {
await ctx.prompter.note(result.notification_message, "MiniMax OAuth");
}
const baseUrl = result.resourceUrl || defaultBaseUrl;
return buildOauthProviderAuthResult({
providerId: PROVIDER_ID,
defaultModel: modelRef(DEFAULT_MODEL),
access: result.access,
refresh: result.refresh,
expires: result.expires,
configPatch: {
models: {
providers: {
[PROVIDER_ID]: {
baseUrl,
models: [],
},
},
},
agents: {
defaults: {
models: {
[modelRef("MiniMax-M2.5")]: { alias: "minimax-m2.5" },
[modelRef("MiniMax-M2.5-highspeed")]: {
alias: "minimax-m2.5-highspeed",
},
[modelRef("MiniMax-M2.5-Lightning")]: {
alias: "minimax-m2.5-lightning",
},
},
},
},
},
notes: [
"MiniMax OAuth tokens auto-refresh. Re-run login if refresh fails or access is revoked.",
`Base URL defaults to ${defaultBaseUrl}. Override models.providers.${PROVIDER_ID}.baseUrl if needed.`,
...(result.notification_message ? [result.notification_message] : []),
],
});
} catch (err) {
const errorMsg = err instanceof Error ? err.message : String(err);
progress.stop(`MiniMax OAuth failed: ${errorMsg}`);
await ctx.prompter.note(
"If OAuth fails, verify your MiniMax account has portal access and try again.",
"MiniMax OAuth",
);
throw err;
}
};
}
const minimaxPortalPlugin = {
id: "minimax-portal-auth",
name: "MiniMax OAuth",
description: "OAuth flow for MiniMax models",
configSchema: emptyPluginConfigSchema(),
register(api: OpenClawPluginApi) {
api.registerProvider({
id: PROVIDER_ID,
label: PROVIDER_LABEL,
docsPath: "/providers/minimax",
catalog: {
run: async (ctx: ProviderCatalogContext) => resolveCatalog(ctx),
},
auth: [
{
id: "oauth",
label: "MiniMax OAuth (Global)",
hint: "Global endpoint - api.minimax.io",
kind: "device_code",
run: createOAuthHandler("global"),
},
{
id: "oauth-cn",
label: "MiniMax OAuth (CN)",
hint: "CN endpoint - api.minimaxi.com",
kind: "device_code",
run: createOAuthHandler("cn"),
},
],
});
},
};
export default minimaxPortalPlugin;

View File

@ -1,9 +0,0 @@
{
"id": "minimax-portal-auth",
"providers": ["minimax-portal"],
"configSchema": {
"type": "object",
"additionalProperties": false,
"properties": {}
}
}

View File

@ -1,12 +0,0 @@
{
"name": "@openclaw/minimax-portal-auth",
"version": "2026.3.14",
"private": true,
"description": "OpenClaw MiniMax Portal OAuth provider plugin",
"type": "module",
"openclaw": {
"extensions": [
"./index.ts"
]
}
}

View File

@ -0,0 +1,37 @@
# MiniMax (OpenClaw plugin)
Bundled MiniMax plugin for both:
- API-key provider setup (`minimax`)
- Coding Plan OAuth setup (`minimax-portal`)
## Enable
```bash
openclaw plugins enable minimax
```
Restart the Gateway after enabling.
```bash
openclaw gateway restart
```
## Authenticate
OAuth:
```bash
openclaw models auth login --provider minimax-portal --set-default
```
API key:
```bash
openclaw onboard --auth-choice minimax-global-api
```
## Notes
- MiniMax OAuth uses a user-code login flow.
- OAuth currently targets the Coding Plan path.

View File

@ -1,35 +1,165 @@
import { emptyPluginConfigSchema, type OpenClawPluginApi } from "openclaw/plugin-sdk/core"; import {
import { buildMinimaxProvider } from "../../src/agents/models-config.providers.static.js"; buildOauthProviderAuthResult,
emptyPluginConfigSchema,
type OpenClawPluginApi,
type ProviderAuthContext,
type ProviderAuthResult,
type ProviderCatalogContext,
} from "openclaw/plugin-sdk/minimax-portal-auth";
import { ensureAuthProfileStore, listProfilesForProvider } from "../../src/agents/auth-profiles.js";
import { MINIMAX_OAUTH_MARKER } from "../../src/agents/model-auth-markers.js";
import {
buildMinimaxPortalProvider,
buildMinimaxProvider,
} from "../../src/agents/models-config.providers.static.js";
import { fetchMinimaxUsage } from "../../src/infra/provider-usage.fetch.js"; import { fetchMinimaxUsage } from "../../src/infra/provider-usage.fetch.js";
import { loginMiniMaxPortalOAuth, type MiniMaxRegion } from "./oauth.js";
const PROVIDER_ID = "minimax"; const API_PROVIDER_ID = "minimax";
const PORTAL_PROVIDER_ID = "minimax-portal";
const PROVIDER_LABEL = "MiniMax";
const DEFAULT_MODEL = "MiniMax-M2.5";
const DEFAULT_BASE_URL_CN = "https://api.minimaxi.com/anthropic";
const DEFAULT_BASE_URL_GLOBAL = "https://api.minimax.io/anthropic";
function getDefaultBaseUrl(region: MiniMaxRegion): string {
return region === "cn" ? DEFAULT_BASE_URL_CN : DEFAULT_BASE_URL_GLOBAL;
}
function modelRef(modelId: string): string {
return `${PORTAL_PROVIDER_ID}/${modelId}`;
}
function buildPortalProviderCatalog(params: { baseUrl: string; apiKey: string }) {
return {
...buildMinimaxPortalProvider(),
baseUrl: params.baseUrl,
apiKey: params.apiKey,
};
}
function resolveApiCatalog(ctx: ProviderCatalogContext) {
const apiKey = ctx.resolveProviderApiKey(API_PROVIDER_ID).apiKey;
if (!apiKey) {
return null;
}
return {
provider: {
...buildMinimaxProvider(),
apiKey,
},
};
}
function resolvePortalCatalog(ctx: ProviderCatalogContext) {
const explicitProvider = ctx.config.models?.providers?.[PORTAL_PROVIDER_ID];
const envApiKey = ctx.resolveProviderApiKey(PORTAL_PROVIDER_ID).apiKey;
const authStore = ensureAuthProfileStore(ctx.agentDir, {
allowKeychainPrompt: false,
});
const hasProfiles = listProfilesForProvider(authStore, PORTAL_PROVIDER_ID).length > 0;
const explicitApiKey =
typeof explicitProvider?.apiKey === "string" ? explicitProvider.apiKey.trim() : undefined;
const apiKey = envApiKey ?? explicitApiKey ?? (hasProfiles ? MINIMAX_OAUTH_MARKER : undefined);
if (!apiKey) {
return null;
}
const explicitBaseUrl =
typeof explicitProvider?.baseUrl === "string" ? explicitProvider.baseUrl.trim() : undefined;
return {
provider: buildPortalProviderCatalog({
baseUrl: explicitBaseUrl || DEFAULT_BASE_URL_GLOBAL,
apiKey,
}),
};
}
function createOAuthHandler(region: MiniMaxRegion) {
const defaultBaseUrl = getDefaultBaseUrl(region);
const regionLabel = region === "cn" ? "CN" : "Global";
return async (ctx: ProviderAuthContext): Promise<ProviderAuthResult> => {
const progress = ctx.prompter.progress(`Starting MiniMax OAuth (${regionLabel})…`);
try {
const result = await loginMiniMaxPortalOAuth({
openUrl: ctx.openUrl,
note: ctx.prompter.note,
progress,
region,
});
progress.stop("MiniMax OAuth complete");
if (result.notification_message) {
await ctx.prompter.note(result.notification_message, "MiniMax OAuth");
}
const baseUrl = result.resourceUrl || defaultBaseUrl;
return buildOauthProviderAuthResult({
providerId: PORTAL_PROVIDER_ID,
defaultModel: modelRef(DEFAULT_MODEL),
access: result.access,
refresh: result.refresh,
expires: result.expires,
configPatch: {
models: {
providers: {
[PORTAL_PROVIDER_ID]: {
baseUrl,
models: [],
},
},
},
agents: {
defaults: {
models: {
[modelRef("MiniMax-M2.5")]: { alias: "minimax-m2.5" },
[modelRef("MiniMax-M2.5-highspeed")]: {
alias: "minimax-m2.5-highspeed",
},
[modelRef("MiniMax-M2.5-Lightning")]: {
alias: "minimax-m2.5-lightning",
},
},
},
},
},
notes: [
"MiniMax OAuth tokens auto-refresh. Re-run login if refresh fails or access is revoked.",
`Base URL defaults to ${defaultBaseUrl}. Override models.providers.${PORTAL_PROVIDER_ID}.baseUrl if needed.`,
...(result.notification_message ? [result.notification_message] : []),
],
});
} catch (err) {
const errorMsg = err instanceof Error ? err.message : String(err);
progress.stop(`MiniMax OAuth failed: ${errorMsg}`);
await ctx.prompter.note(
"If OAuth fails, verify your MiniMax account has portal access and try again.",
"MiniMax OAuth",
);
throw err;
}
};
}
const minimaxPlugin = { const minimaxPlugin = {
id: PROVIDER_ID, id: API_PROVIDER_ID,
name: "MiniMax Provider", name: "MiniMax",
description: "Bundled MiniMax provider plugin", description: "Bundled MiniMax API-key and OAuth provider plugin",
configSchema: emptyPluginConfigSchema(), configSchema: emptyPluginConfigSchema(),
register(api: OpenClawPluginApi) { register(api: OpenClawPluginApi) {
api.registerProvider({ api.registerProvider({
id: PROVIDER_ID, id: API_PROVIDER_ID,
label: "MiniMax", label: PROVIDER_LABEL,
docsPath: "/providers/minimax", docsPath: "/providers/minimax",
envVars: ["MINIMAX_API_KEY"], envVars: ["MINIMAX_API_KEY"],
auth: [], auth: [],
catalog: { catalog: {
order: "simple", order: "simple",
run: async (ctx) => { run: async (ctx) => resolveApiCatalog(ctx),
const apiKey = ctx.resolveProviderApiKey(PROVIDER_ID).apiKey;
if (!apiKey) {
return null;
}
return {
provider: {
...buildMinimaxProvider(),
apiKey,
},
};
},
}, },
resolveUsageAuth: async (ctx) => { resolveUsageAuth: async (ctx) => {
const apiKey = ctx.resolveApiKeyFromConfigAndStore({ const apiKey = ctx.resolveApiKeyFromConfigAndStore({
@ -40,6 +170,31 @@ const minimaxPlugin = {
fetchUsageSnapshot: async (ctx) => fetchUsageSnapshot: async (ctx) =>
await fetchMinimaxUsage(ctx.token, ctx.timeoutMs, ctx.fetchFn), await fetchMinimaxUsage(ctx.token, ctx.timeoutMs, ctx.fetchFn),
}); });
api.registerProvider({
id: PORTAL_PROVIDER_ID,
label: PROVIDER_LABEL,
docsPath: "/providers/minimax",
catalog: {
run: async (ctx) => resolvePortalCatalog(ctx),
},
auth: [
{
id: "oauth",
label: "MiniMax OAuth (Global)",
hint: "Global endpoint - api.minimax.io",
kind: "device_code",
run: createOAuthHandler("global"),
},
{
id: "oauth-cn",
label: "MiniMax OAuth (CN)",
hint: "CN endpoint - api.minimaxi.com",
kind: "device_code",
run: createOAuthHandler("cn"),
},
],
});
}, },
}; };

View File

@ -161,7 +161,7 @@ async function pollOAuthToken(params: {
return { status: "error", message: "An error occurred. Please try again later" }; return { status: "error", message: "An error occurred. Please try again later" };
} }
if (tokenPayload.status != "success") { if (tokenPayload.status !== "success") {
return { status: "pending", message: "current user code is not authorized" }; return { status: "pending", message: "current user code is not authorized" };
} }
@ -216,29 +216,17 @@ export async function loginMiniMaxPortalOAuth(params: {
region, region,
}); });
// // Debug: print poll result
// await params.note(
// `status: ${result.status}` +
// (result.status === "success" ? `\ntoken: ${JSON.stringify(result.token, null, 2)}` : "") +
// (result.status === "error" ? `\nmessage: ${result.message}` : "") +
// (result.status === "pending" && result.message ? `\nmessage: ${result.message}` : ""),
// "MiniMax OAuth Poll Result",
// );
if (result.status === "success") { if (result.status === "success") {
return result.token; return result.token;
} }
if (result.status === "error") { if (result.status === "error") {
throw new Error(`MiniMax OAuth failed: ${result.message}`); throw new Error(result.message);
}
if (result.status === "pending") {
pollIntervalMs = Math.min(pollIntervalMs * 1.5, 10000);
} }
await new Promise((resolve) => setTimeout(resolve, pollIntervalMs)); await new Promise((resolve) => setTimeout(resolve, pollIntervalMs));
pollIntervalMs = Math.max(pollIntervalMs, 2000);
} }
throw new Error("MiniMax OAuth timed out waiting for authorization."); throw new Error("MiniMax OAuth timed out before authorization completed.");
} }

View File

@ -1,6 +1,6 @@
{ {
"id": "minimax", "id": "minimax",
"providers": ["minimax"], "providers": ["minimax", "minimax-portal"],
"configSchema": { "configSchema": {
"type": "object", "type": "object",
"additionalProperties": false, "additionalProperties": false,

View File

@ -2,7 +2,7 @@
"name": "@openclaw/minimax-provider", "name": "@openclaw/minimax-provider",
"version": "2026.3.14", "version": "2026.3.14",
"private": true, "private": true,
"description": "OpenClaw MiniMax provider plugin", "description": "OpenClaw MiniMax provider and OAuth plugin",
"type": "module", "type": "module",
"openclaw": { "openclaw": {
"extensions": [ "extensions": [

View File

@ -24,8 +24,8 @@ const allowedRawFetchCallsites = new Set([
"extensions/mattermost/src/mattermost/client.ts:211", "extensions/mattermost/src/mattermost/client.ts:211",
"extensions/mattermost/src/mattermost/monitor.ts:230", "extensions/mattermost/src/mattermost/monitor.ts:230",
"extensions/mattermost/src/mattermost/probe.ts:27", "extensions/mattermost/src/mattermost/probe.ts:27",
"extensions/minimax-portal-auth/oauth.ts:71", "extensions/minimax/oauth.ts:62",
"extensions/minimax-portal-auth/oauth.ts:112", "extensions/minimax/oauth.ts:93",
"extensions/msteams/src/graph.ts:39", "extensions/msteams/src/graph.ts:39",
"extensions/nextcloud-talk/src/room-info.ts:92", "extensions/nextcloud-talk/src/room-info.ts:92",
"extensions/nextcloud-talk/src/send.ts:107", "extensions/nextcloud-talk/src/send.ts:107",

View File

@ -22,7 +22,7 @@ export async function applyAuthChoiceMiniMax(
if (params.authChoice === "minimax-global-oauth") { if (params.authChoice === "minimax-global-oauth") {
return await applyAuthChoicePluginProvider(params, { return await applyAuthChoicePluginProvider(params, {
authChoice: "minimax-global-oauth", authChoice: "minimax-global-oauth",
pluginId: "minimax-portal-auth", pluginId: "minimax",
providerId: "minimax-portal", providerId: "minimax-portal",
methodId: "oauth", methodId: "oauth",
label: "MiniMax", label: "MiniMax",
@ -32,7 +32,7 @@ export async function applyAuthChoiceMiniMax(
if (params.authChoice === "minimax-cn-oauth") { if (params.authChoice === "minimax-cn-oauth") {
return await applyAuthChoicePluginProvider(params, { return await applyAuthChoicePluginProvider(params, {
authChoice: "minimax-cn-oauth", authChoice: "minimax-cn-oauth",
pluginId: "minimax-portal-auth", pluginId: "minimax",
providerId: "minimax-portal", providerId: "minimax-portal",
methodId: "oauth-cn", methodId: "oauth-cn",
label: "MiniMax CN", label: "MiniMax CN",

View File

@ -310,6 +310,25 @@ describe("applyPluginAutoEnable", () => {
expect(result.config.plugins?.entries?.google?.enabled).toBe(true); expect(result.config.plugins?.entries?.google?.enabled).toBe(true);
}); });
it("auto-enables minimax when minimax-portal profiles exist", () => {
const result = applyPluginAutoEnable({
config: {
auth: {
profiles: {
"minimax-portal:default": {
provider: "minimax-portal",
mode: "oauth",
},
},
},
},
env: {},
});
expect(result.config.plugins?.entries?.minimax?.enabled).toBe(true);
expect(result.config.plugins?.entries?.["minimax-portal-auth"]).toBeUndefined();
});
it("auto-enables acpx plugin when ACP is configured", () => { it("auto-enables acpx plugin when ACP is configured", () => {
const result = applyPluginAutoEnable({ const result = applyPluginAutoEnable({
config: { config: {

View File

@ -31,7 +31,7 @@ const PROVIDER_PLUGIN_IDS: Array<{ pluginId: string; providerId: string }> = [
{ pluginId: "google", providerId: "google-gemini-cli" }, { pluginId: "google", providerId: "google-gemini-cli" },
{ pluginId: "qwen-portal-auth", providerId: "qwen-portal" }, { pluginId: "qwen-portal-auth", providerId: "qwen-portal" },
{ pluginId: "copilot-proxy", providerId: "copilot-proxy" }, { pluginId: "copilot-proxy", providerId: "copilot-proxy" },
{ pluginId: "minimax-portal-auth", providerId: "minimax-portal" }, { pluginId: "minimax", providerId: "minimax-portal" },
]; ];
function hasNonEmptyString(value: unknown): boolean { function hasNonEmptyString(value: unknown): boolean {

View File

@ -1,5 +1,5 @@
// Narrow plugin-sdk surface for the bundled minimax-portal-auth plugin. // Narrow plugin-sdk surface for MiniMax OAuth helpers used by the bundled minimax plugin.
// Keep this list additive and scoped to symbols used under extensions/minimax-portal-auth. // Keep this list additive and scoped to MiniMax OAuth support code.
export { emptyPluginConfigSchema } from "../plugins/config-schema.js"; export { emptyPluginConfigSchema } from "../plugins/config-schema.js";
export { buildOauthProviderAuthResult } from "./provider-auth-result.js"; export { buildOauthProviderAuthResult } from "./provider-auth-result.js";

View File

@ -80,18 +80,22 @@ describe("normalizePluginsConfig", () => {
it("normalizes legacy plugin ids to their merged bundled plugin id", () => { it("normalizes legacy plugin ids to their merged bundled plugin id", () => {
const result = normalizePluginsConfig({ const result = normalizePluginsConfig({
allow: ["openai-codex"], allow: ["openai-codex", "minimax-portal-auth"],
deny: ["openai-codex"], deny: ["openai-codex", "minimax-portal-auth"],
entries: { entries: {
"openai-codex": { "openai-codex": {
enabled: true, enabled: true,
}, },
"minimax-portal-auth": {
enabled: false,
},
}, },
}); });
expect(result.allow).toEqual(["openai"]); expect(result.allow).toEqual(["openai", "minimax"]);
expect(result.deny).toEqual(["openai"]); expect(result.deny).toEqual(["openai", "minimax"]);
expect(result.entries.openai?.enabled).toBe(true); expect(result.entries.openai?.enabled).toBe(true);
expect(result.entries.minimax?.enabled).toBe(false);
}); });
}); });

View File

@ -33,7 +33,6 @@ export const BUNDLED_ENABLED_BY_DEFAULT = new Set<string>([
"kilocode", "kilocode",
"kimi-coding", "kimi-coding",
"minimax", "minimax",
"minimax-portal-auth",
"mistral", "mistral",
"modelstudio", "modelstudio",
"moonshot", "moonshot",
@ -60,6 +59,7 @@ export const BUNDLED_ENABLED_BY_DEFAULT = new Set<string>([
const PLUGIN_ID_ALIASES: Readonly<Record<string, string>> = { const PLUGIN_ID_ALIASES: Readonly<Record<string, string>> = {
"openai-codex": "openai", "openai-codex": "openai",
"minimax-portal-auth": "minimax",
}; };
function normalizePluginId(id: string): string { function normalizePluginId(id: string): string {

View File

@ -16,7 +16,6 @@ const BUNDLED_PROVIDER_ALLOWLIST_COMPAT_PLUGIN_IDS = [
"kilocode", "kilocode",
"kimi-coding", "kimi-coding",
"minimax", "minimax",
"minimax-portal-auth",
"mistral", "mistral",
"modelstudio", "modelstudio",
"moonshot", "moonshot",