refactor: merge minimax bundled plugins
This commit is contained in:
parent
6513749ef6
commit
47a9c1a893
@ -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.
|
||||
- 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/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/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.
|
||||
|
||||
|
||||
@ -42,7 +42,7 @@ MiniMax highlights these improvements in M2.5:
|
||||
Enable the bundled OAuth plugin and authenticate:
|
||||
|
||||
```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 onboard --auth-choice minimax-portal
|
||||
```
|
||||
@ -52,7 +52,7 @@ You will be prompted to select an endpoint:
|
||||
- **Global** - International users (`api.minimax.io`)
|
||||
- **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)
|
||||
|
||||
|
||||
@ -172,8 +172,7 @@ Important trust note:
|
||||
- Hugging Face provider catalog — bundled as `huggingface` (enabled by default)
|
||||
- Kilo Gateway provider runtime — bundled as `kilocode` (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 OAuth (provider auth + catalog) — bundled as `minimax-portal-auth` (enabled by default)
|
||||
- MiniMax provider catalog + usage + OAuth — bundled as `minimax` (enabled by default; owns `minimax` and `minimax-portal`)
|
||||
- Mistral provider capabilities — bundled as `mistral` (enabled by default)
|
||||
- Model Studio provider catalog — bundled as `modelstudio` (enabled by default)
|
||||
- Moonshot provider runtime — bundled as `moonshot` (enabled by default)
|
||||
@ -664,7 +663,7 @@ Default-on bundled plugin examples:
|
||||
- `kilocode`
|
||||
- `kimi-coding`
|
||||
- `minimax`
|
||||
- `minimax-portal-auth`
|
||||
- `minimax`
|
||||
- `modelstudio`
|
||||
- `moonshot`
|
||||
- `nvidia`
|
||||
|
||||
@ -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
|
||||
@ -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;
|
||||
@ -1,9 +0,0 @@
|
||||
{
|
||||
"id": "minimax-portal-auth",
|
||||
"providers": ["minimax-portal"],
|
||||
"configSchema": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {}
|
||||
}
|
||||
}
|
||||
@ -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"
|
||||
]
|
||||
}
|
||||
}
|
||||
37
extensions/minimax/README.md
Normal file
37
extensions/minimax/README.md
Normal 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.
|
||||
@ -1,25 +1,45 @@
|
||||
import { emptyPluginConfigSchema, type OpenClawPluginApi } from "openclaw/plugin-sdk/core";
|
||||
import { buildMinimaxProvider } from "../../src/agents/models-config.providers.static.js";
|
||||
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,
|
||||
buildMinimaxProvider,
|
||||
} from "../../src/agents/models-config.providers.static.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";
|
||||
|
||||
const minimaxPlugin = {
|
||||
id: PROVIDER_ID,
|
||||
name: "MiniMax Provider",
|
||||
description: "Bundled MiniMax provider plugin",
|
||||
configSchema: emptyPluginConfigSchema(),
|
||||
register(api: OpenClawPluginApi) {
|
||||
api.registerProvider({
|
||||
id: PROVIDER_ID,
|
||||
label: "MiniMax",
|
||||
docsPath: "/providers/minimax",
|
||||
envVars: ["MINIMAX_API_KEY"],
|
||||
auth: [],
|
||||
catalog: {
|
||||
order: "simple",
|
||||
run: async (ctx) => {
|
||||
const apiKey = ctx.resolveProviderApiKey(PROVIDER_ID).apiKey;
|
||||
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;
|
||||
}
|
||||
@ -29,8 +49,118 @@ const minimaxPlugin = {
|
||||
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 = {
|
||||
id: API_PROVIDER_ID,
|
||||
name: "MiniMax",
|
||||
description: "Bundled MiniMax API-key and OAuth provider plugin",
|
||||
configSchema: emptyPluginConfigSchema(),
|
||||
register(api: OpenClawPluginApi) {
|
||||
api.registerProvider({
|
||||
id: API_PROVIDER_ID,
|
||||
label: PROVIDER_LABEL,
|
||||
docsPath: "/providers/minimax",
|
||||
envVars: ["MINIMAX_API_KEY"],
|
||||
auth: [],
|
||||
catalog: {
|
||||
order: "simple",
|
||||
run: async (ctx) => resolveApiCatalog(ctx),
|
||||
},
|
||||
resolveUsageAuth: async (ctx) => {
|
||||
const apiKey = ctx.resolveApiKeyFromConfigAndStore({
|
||||
envDirect: [ctx.env.MINIMAX_CODE_PLAN_KEY, ctx.env.MINIMAX_API_KEY],
|
||||
@ -40,6 +170,31 @@ const minimaxPlugin = {
|
||||
fetchUsageSnapshot: async (ctx) =>
|
||||
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"),
|
||||
},
|
||||
],
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
@ -161,7 +161,7 @@ async function pollOAuthToken(params: {
|
||||
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" };
|
||||
}
|
||||
|
||||
@ -216,29 +216,17 @@ export async function loginMiniMaxPortalOAuth(params: {
|
||||
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") {
|
||||
return result.token;
|
||||
}
|
||||
|
||||
if (result.status === "error") {
|
||||
throw new Error(`MiniMax OAuth failed: ${result.message}`);
|
||||
}
|
||||
|
||||
if (result.status === "pending") {
|
||||
pollIntervalMs = Math.min(pollIntervalMs * 1.5, 10000);
|
||||
throw new Error(result.message);
|
||||
}
|
||||
|
||||
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.");
|
||||
}
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"id": "minimax",
|
||||
"providers": ["minimax"],
|
||||
"providers": ["minimax", "minimax-portal"],
|
||||
"configSchema": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
"name": "@openclaw/minimax-provider",
|
||||
"version": "2026.3.14",
|
||||
"private": true,
|
||||
"description": "OpenClaw MiniMax provider plugin",
|
||||
"description": "OpenClaw MiniMax provider and OAuth plugin",
|
||||
"type": "module",
|
||||
"openclaw": {
|
||||
"extensions": [
|
||||
|
||||
@ -24,8 +24,8 @@ const allowedRawFetchCallsites = new Set([
|
||||
"extensions/mattermost/src/mattermost/client.ts:211",
|
||||
"extensions/mattermost/src/mattermost/monitor.ts:230",
|
||||
"extensions/mattermost/src/mattermost/probe.ts:27",
|
||||
"extensions/minimax-portal-auth/oauth.ts:71",
|
||||
"extensions/minimax-portal-auth/oauth.ts:112",
|
||||
"extensions/minimax/oauth.ts:62",
|
||||
"extensions/minimax/oauth.ts:93",
|
||||
"extensions/msteams/src/graph.ts:39",
|
||||
"extensions/nextcloud-talk/src/room-info.ts:92",
|
||||
"extensions/nextcloud-talk/src/send.ts:107",
|
||||
|
||||
@ -22,7 +22,7 @@ export async function applyAuthChoiceMiniMax(
|
||||
if (params.authChoice === "minimax-global-oauth") {
|
||||
return await applyAuthChoicePluginProvider(params, {
|
||||
authChoice: "minimax-global-oauth",
|
||||
pluginId: "minimax-portal-auth",
|
||||
pluginId: "minimax",
|
||||
providerId: "minimax-portal",
|
||||
methodId: "oauth",
|
||||
label: "MiniMax",
|
||||
@ -32,7 +32,7 @@ export async function applyAuthChoiceMiniMax(
|
||||
if (params.authChoice === "minimax-cn-oauth") {
|
||||
return await applyAuthChoicePluginProvider(params, {
|
||||
authChoice: "minimax-cn-oauth",
|
||||
pluginId: "minimax-portal-auth",
|
||||
pluginId: "minimax",
|
||||
providerId: "minimax-portal",
|
||||
methodId: "oauth-cn",
|
||||
label: "MiniMax CN",
|
||||
|
||||
@ -310,6 +310,25 @@ describe("applyPluginAutoEnable", () => {
|
||||
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", () => {
|
||||
const result = applyPluginAutoEnable({
|
||||
config: {
|
||||
|
||||
@ -31,7 +31,7 @@ const PROVIDER_PLUGIN_IDS: Array<{ pluginId: string; providerId: string }> = [
|
||||
{ pluginId: "google", providerId: "google-gemini-cli" },
|
||||
{ pluginId: "qwen-portal-auth", providerId: "qwen-portal" },
|
||||
{ pluginId: "copilot-proxy", providerId: "copilot-proxy" },
|
||||
{ pluginId: "minimax-portal-auth", providerId: "minimax-portal" },
|
||||
{ pluginId: "minimax", providerId: "minimax-portal" },
|
||||
];
|
||||
|
||||
function hasNonEmptyString(value: unknown): boolean {
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
// Narrow plugin-sdk surface for the bundled minimax-portal-auth plugin.
|
||||
// Keep this list additive and scoped to symbols used under extensions/minimax-portal-auth.
|
||||
// Narrow plugin-sdk surface for MiniMax OAuth helpers used by the bundled minimax plugin.
|
||||
// Keep this list additive and scoped to MiniMax OAuth support code.
|
||||
|
||||
export { emptyPluginConfigSchema } from "../plugins/config-schema.js";
|
||||
export { buildOauthProviderAuthResult } from "./provider-auth-result.js";
|
||||
|
||||
@ -80,18 +80,22 @@ describe("normalizePluginsConfig", () => {
|
||||
|
||||
it("normalizes legacy plugin ids to their merged bundled plugin id", () => {
|
||||
const result = normalizePluginsConfig({
|
||||
allow: ["openai-codex"],
|
||||
deny: ["openai-codex"],
|
||||
allow: ["openai-codex", "minimax-portal-auth"],
|
||||
deny: ["openai-codex", "minimax-portal-auth"],
|
||||
entries: {
|
||||
"openai-codex": {
|
||||
enabled: true,
|
||||
},
|
||||
"minimax-portal-auth": {
|
||||
enabled: false,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
expect(result.allow).toEqual(["openai"]);
|
||||
expect(result.deny).toEqual(["openai"]);
|
||||
expect(result.allow).toEqual(["openai", "minimax"]);
|
||||
expect(result.deny).toEqual(["openai", "minimax"]);
|
||||
expect(result.entries.openai?.enabled).toBe(true);
|
||||
expect(result.entries.minimax?.enabled).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@ -33,7 +33,6 @@ export const BUNDLED_ENABLED_BY_DEFAULT = new Set<string>([
|
||||
"kilocode",
|
||||
"kimi-coding",
|
||||
"minimax",
|
||||
"minimax-portal-auth",
|
||||
"mistral",
|
||||
"modelstudio",
|
||||
"moonshot",
|
||||
@ -60,6 +59,7 @@ export const BUNDLED_ENABLED_BY_DEFAULT = new Set<string>([
|
||||
|
||||
const PLUGIN_ID_ALIASES: Readonly<Record<string, string>> = {
|
||||
"openai-codex": "openai",
|
||||
"minimax-portal-auth": "minimax",
|
||||
};
|
||||
|
||||
function normalizePluginId(id: string): string {
|
||||
|
||||
@ -16,7 +16,6 @@ const BUNDLED_PROVIDER_ALLOWLIST_COMPAT_PLUGIN_IDS = [
|
||||
"kilocode",
|
||||
"kimi-coding",
|
||||
"minimax",
|
||||
"minimax-portal-auth",
|
||||
"mistral",
|
||||
"modelstudio",
|
||||
"moonshot",
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user