mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-06 05:10:44 +00:00
fix(web-search): allow MiniMax OAuth search credentials
Co-authored-by: 周鹤0668001310 <zhou.he3@xydigit.com>
This commit is contained in:
@@ -24,6 +24,7 @@ Docs: https://docs.openclaw.ai
|
||||
### Fixes
|
||||
|
||||
- Telegram: inherit the process DNS result order for Bot API transport and downgrade recovered sticky IPv4 fallback promotions to debug logs, while keeping pinned-IP escalation warnings visible. Fixes #75904. Thanks @highfly-hi and @neeravmakwana.
|
||||
- Web search/MiniMax: allow `MINIMAX_OAUTH_TOKEN` to satisfy MiniMax Search credentials, so OAuth-authorized MiniMax Token Plan setups do not need a separate web-search key. Fixes #65768. Thanks @kikibrian and @zhouhe-xydt.
|
||||
- Subagents: honor `sessions_spawn` with `expectsCompletionMessage: false` by skipping parent completion handoff delivery while still running child cleanup. Fixes #75848. Thanks @alfredjbclaw.
|
||||
- Gateway/logging: keep deferred channel startup logs on the subsystem logger, so Slack, Discord, Telegram, and voice-call startup messages keep timestamped prefixes. Thanks @vincentkoc.
|
||||
- ACP/Discord: suppress completion announce delivery for inline thread-bound ACP session runs, so Discord thread-bound ACP replies are not delivered twice. Fixes #60780. Thanks @solavrc.
|
||||
|
||||
@@ -13,7 +13,7 @@ MiniMax also provides:
|
||||
- Bundled speech synthesis via T2A v2
|
||||
- Bundled image understanding via `MiniMax-VL-01`
|
||||
- Bundled music generation via `music-2.6`
|
||||
- Bundled `web_search` through the MiniMax Coding Plan search API
|
||||
- Bundled `web_search` through the MiniMax Token Plan search API
|
||||
|
||||
Provider split:
|
||||
|
||||
@@ -357,16 +357,16 @@ when the bundled text-provider catalog still shows text-only M2.7 chat refs.
|
||||
|
||||
### Web search
|
||||
|
||||
The MiniMax plugin also registers `web_search` through the MiniMax Coding Plan
|
||||
The MiniMax plugin also registers `web_search` through the MiniMax Token Plan
|
||||
search API.
|
||||
|
||||
- Provider id: `minimax`
|
||||
- Structured results: titles, URLs, snippets, related queries
|
||||
- Preferred env var: `MINIMAX_CODE_PLAN_KEY`
|
||||
- Accepted env alias: `MINIMAX_CODING_API_KEY`
|
||||
- Compatibility fallback: `MINIMAX_API_KEY` when it already points at a coding-plan token
|
||||
- Accepted env aliases: `MINIMAX_CODING_API_KEY`, `MINIMAX_OAUTH_TOKEN`
|
||||
- Compatibility fallback: `MINIMAX_API_KEY` when it already points at a token-plan credential
|
||||
- Region reuse: `plugins.entries.minimax.config.webSearch.region`, then `MINIMAX_API_HOST`, then MiniMax provider base URLs
|
||||
- Search stays on provider id `minimax`; OAuth CN/global setup can still steer region indirectly through `models.providers.minimax-portal.baseUrl`
|
||||
- Search stays on provider id `minimax`; OAuth CN/global setup can steer region indirectly through `models.providers.minimax-portal.baseUrl` and can provide bearer auth through `MINIMAX_OAUTH_TOKEN`
|
||||
|
||||
Config lives under `plugins.entries.minimax.config.webSearch.*`.
|
||||
|
||||
@@ -496,7 +496,7 @@ More help: [Troubleshooting](/help/troubleshooting) and [FAQ](/help/faq).
|
||||
Shared video tool parameters and provider selection.
|
||||
</Card>
|
||||
<Card title="MiniMax Search" href="/tools/minimax-search" icon="magnifying-glass">
|
||||
Web search configuration via MiniMax Coding Plan.
|
||||
Web search configuration via MiniMax Token Plan.
|
||||
</Card>
|
||||
<Card title="Troubleshooting" href="/help/troubleshooting" icon="wrench">
|
||||
General troubleshooting and FAQ.
|
||||
|
||||
@@ -1,22 +1,23 @@
|
||||
---
|
||||
summary: "MiniMax Search via the Coding Plan search API"
|
||||
summary: "MiniMax Search via the Token Plan search API"
|
||||
read_when:
|
||||
- You want to use MiniMax for web_search
|
||||
- You need a MiniMax Coding Plan key
|
||||
- You need a MiniMax Token Plan key or OAuth token
|
||||
- You want MiniMax CN/global search host guidance
|
||||
title: "MiniMax search"
|
||||
---
|
||||
|
||||
OpenClaw supports MiniMax as a `web_search` provider through the MiniMax
|
||||
Coding Plan search API. It returns structured search results with titles, URLs,
|
||||
Token Plan search API. It returns structured search results with titles, URLs,
|
||||
snippets, and related queries.
|
||||
|
||||
## Get a Coding Plan key
|
||||
## Get a Token Plan credential
|
||||
|
||||
<Steps>
|
||||
<Step title="Create a key">
|
||||
Create or copy a MiniMax Coding Plan key from
|
||||
Create or copy a MiniMax Token Plan key from
|
||||
[MiniMax Platform](https://platform.minimax.io/user-center/basic-information/interface-key).
|
||||
OAuth setups can reuse `MINIMAX_OAUTH_TOKEN` instead.
|
||||
</Step>
|
||||
<Step title="Store the key">
|
||||
Set `MINIMAX_CODE_PLAN_KEY` in the Gateway environment, or configure via:
|
||||
@@ -28,8 +29,9 @@ snippets, and related queries.
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
OpenClaw also accepts `MINIMAX_CODING_API_KEY` as an env alias. `MINIMAX_API_KEY`
|
||||
is still read as a compatibility fallback when it already points at a coding-plan token.
|
||||
OpenClaw also accepts `MINIMAX_CODING_API_KEY` and `MINIMAX_OAUTH_TOKEN` as env
|
||||
aliases. `MINIMAX_API_KEY` is still read as a compatibility fallback when it
|
||||
already points at a token-plan credential.
|
||||
|
||||
## Config
|
||||
|
||||
@@ -40,7 +42,7 @@ is still read as a compatibility fallback when it already points at a coding-pla
|
||||
minimax: {
|
||||
config: {
|
||||
webSearch: {
|
||||
apiKey: "sk-cp-...", // optional if MINIMAX_CODE_PLAN_KEY is set
|
||||
apiKey: "sk-cp-...", // optional if a MiniMax Token Plan env var is set
|
||||
region: "global", // or "cn"
|
||||
},
|
||||
},
|
||||
@@ -57,7 +59,8 @@ is still read as a compatibility fallback when it already points at a coding-pla
|
||||
}
|
||||
```
|
||||
|
||||
**Environment alternative:** set `MINIMAX_CODE_PLAN_KEY` in the Gateway environment.
|
||||
**Environment alternative:** set `MINIMAX_CODE_PLAN_KEY` or `MINIMAX_OAUTH_TOKEN`
|
||||
in the Gateway environment.
|
||||
For a gateway install, put it in `~/.openclaw/.env`.
|
||||
|
||||
## Region selection
|
||||
@@ -80,7 +83,8 @@ automatically keeps MiniMax Search on the CN host too.
|
||||
|
||||
Even when you authenticated MiniMax through the OAuth `minimax-portal` path,
|
||||
web search still registers as provider id `minimax`; the OAuth provider base URL
|
||||
is only used as a region hint for CN/global host selection.
|
||||
is used as a region hint for CN/global host selection, and `MINIMAX_OAUTH_TOKEN`
|
||||
can satisfy the MiniMax Search bearer credential.
|
||||
|
||||
## Supported parameters
|
||||
|
||||
|
||||
@@ -79,7 +79,7 @@ local while `web_search` and `x_search` can use xAI Responses under the hood.
|
||||
AI-synthesized answers with citations via Moonshot web search.
|
||||
</Card>
|
||||
<Card title="MiniMax Search" icon="globe" href="/tools/minimax-search">
|
||||
Structured results via the MiniMax Coding Plan search API.
|
||||
Structured results via the MiniMax Token Plan search API.
|
||||
</Card>
|
||||
<Card title="Ollama Web Search" icon="globe" href="/tools/ollama-search">
|
||||
Search via a signed-in local Ollama host or the hosted Ollama API.
|
||||
@@ -106,7 +106,7 @@ local while `web_search` and `x_search` can use xAI Responses under the hood.
|
||||
| [Gemini](/tools/gemini-search) | AI-synthesized + citations | -- | `GEMINI_API_KEY` |
|
||||
| [Grok](/tools/grok-search) | AI-synthesized + citations | -- | `XAI_API_KEY` |
|
||||
| [Kimi](/tools/kimi-search) | AI-synthesized + citations | -- | `KIMI_API_KEY` / `MOONSHOT_API_KEY` |
|
||||
| [MiniMax Search](/tools/minimax-search) | Structured snippets | Region (`global` / `cn`) | `MINIMAX_CODE_PLAN_KEY` / `MINIMAX_CODING_API_KEY` |
|
||||
| [MiniMax Search](/tools/minimax-search) | Structured snippets | Region (`global` / `cn`) | `MINIMAX_CODE_PLAN_KEY` / `MINIMAX_CODING_API_KEY` / `MINIMAX_OAUTH_TOKEN` |
|
||||
| [Ollama Web Search](/tools/ollama-search) | Structured snippets | -- | None for signed-in local hosts; `OLLAMA_API_KEY` for direct `https://ollama.com` search |
|
||||
| [Perplexity](/tools/perplexity-search) | Structured snippets | Country, language, time, domains, content limits | `PERPLEXITY_API_KEY` / `OPENROUTER_API_KEY` |
|
||||
| [SearXNG](/tools/searxng-search) | Structured snippets | Categories, language | None (self-hosted) |
|
||||
@@ -164,7 +164,7 @@ first one that is ready:
|
||||
API-backed providers first:
|
||||
|
||||
1. **Brave** -- `BRAVE_API_KEY` or `plugins.entries.brave.config.webSearch.apiKey` (order 10)
|
||||
2. **MiniMax Search** -- `MINIMAX_CODE_PLAN_KEY` / `MINIMAX_CODING_API_KEY` or `plugins.entries.minimax.config.webSearch.apiKey` (order 15)
|
||||
2. **MiniMax Search** -- `MINIMAX_CODE_PLAN_KEY` / `MINIMAX_CODING_API_KEY` / `MINIMAX_OAUTH_TOKEN` or `plugins.entries.minimax.config.webSearch.apiKey` (order 15)
|
||||
3. **Gemini** -- `plugins.entries.google.config.webSearch.apiKey`, `GEMINI_API_KEY`, or `models.providers.google.apiKey` (order 20)
|
||||
4. **Grok** -- `XAI_API_KEY` or `plugins.entries.xai.config.webSearch.apiKey` (order 30)
|
||||
5. **Kimi** -- `KIMI_API_KEY` / `MOONSHOT_API_KEY` or `plugins.entries.moonshot.config.webSearch.apiKey` (order 40)
|
||||
|
||||
@@ -246,7 +246,7 @@ describe("minimax provider hooks", () => {
|
||||
expect(webSearchProviders[0]).toMatchObject({
|
||||
id: "minimax",
|
||||
label: "MiniMax Search",
|
||||
envVars: ["MINIMAX_CODE_PLAN_KEY", "MINIMAX_CODING_API_KEY"],
|
||||
envVars: ["MINIMAX_CODE_PLAN_KEY", "MINIMAX_CODING_API_KEY", "MINIMAX_OAUTH_TOKEN"],
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -12,6 +12,7 @@ const MINIMAX_API_KEY = process.env.MINIMAX_API_KEY?.trim() ?? "";
|
||||
const MINIMAX_SEARCH_KEY =
|
||||
process.env.MINIMAX_CODE_PLAN_KEY?.trim() ||
|
||||
process.env.MINIMAX_CODING_API_KEY?.trim() ||
|
||||
process.env.MINIMAX_OAUTH_TOKEN?.trim() ||
|
||||
MINIMAX_API_KEY ||
|
||||
"";
|
||||
const MINIMAX_TTS_TOKEN_PLAN_KEY =
|
||||
|
||||
@@ -97,8 +97,8 @@
|
||||
},
|
||||
"uiHints": {
|
||||
"webSearch.apiKey": {
|
||||
"label": "MiniMax Coding Plan key",
|
||||
"help": "MiniMax Coding Plan key (fallback: MINIMAX_CODE_PLAN_KEY, MINIMAX_CODING_API_KEY, or MINIMAX_API_KEY if it already points at a coding-plan token).",
|
||||
"label": "MiniMax Token Plan key",
|
||||
"help": "MiniMax Token Plan key or OAuth token (fallback: MINIMAX_CODE_PLAN_KEY, MINIMAX_CODING_API_KEY, MINIMAX_OAUTH_TOKEN, or MINIMAX_API_KEY if it already points at a token-plan credential).",
|
||||
"sensitive": true,
|
||||
"placeholder": "sk-cp-..."
|
||||
},
|
||||
|
||||
@@ -26,7 +26,11 @@ import { normalizeOptionalString } from "openclaw/plugin-sdk/text-runtime";
|
||||
|
||||
const MINIMAX_SEARCH_ENDPOINT_GLOBAL = "https://api.minimax.io/v1/coding_plan/search";
|
||||
const MINIMAX_SEARCH_ENDPOINT_CN = "https://api.minimaxi.com/v1/coding_plan/search";
|
||||
const MINIMAX_CODING_PLAN_ENV_VARS = ["MINIMAX_CODE_PLAN_KEY", "MINIMAX_CODING_API_KEY"] as const;
|
||||
const MINIMAX_TOKEN_PLAN_ENV_VARS = [
|
||||
"MINIMAX_CODE_PLAN_KEY",
|
||||
"MINIMAX_CODING_API_KEY",
|
||||
"MINIMAX_OAUTH_TOKEN",
|
||||
] as const;
|
||||
|
||||
type MiniMaxSearchResult = {
|
||||
title?: string;
|
||||
@@ -51,7 +55,7 @@ type MiniMaxSearchResponse = {
|
||||
function resolveMiniMaxApiKey(searchConfig?: SearchConfigRecord): string | undefined {
|
||||
return (
|
||||
readConfiguredSecretString(searchConfig?.apiKey, "tools.web.search.apiKey") ??
|
||||
readProviderEnvValue([...MINIMAX_CODING_PLAN_ENV_VARS, "MINIMAX_API_KEY"])
|
||||
readProviderEnvValue([...MINIMAX_TOKEN_PLAN_ENV_VARS, "MINIMAX_API_KEY"])
|
||||
);
|
||||
}
|
||||
|
||||
@@ -182,7 +186,7 @@ async function runMiniMaxSearch(params: {
|
||||
function missingMiniMaxKeyPayload() {
|
||||
return {
|
||||
error: "missing_minimax_api_key",
|
||||
message: `web_search (minimax) needs a MiniMax Coding Plan key. Run \`${formatCliCommand("openclaw configure --section web")}\` to store it, or set MINIMAX_CODE_PLAN_KEY, MINIMAX_CODING_API_KEY, or MINIMAX_API_KEY in the Gateway environment.`,
|
||||
message: `web_search (minimax) needs a MiniMax Token Plan key or OAuth token. Run \`${formatCliCommand("openclaw configure --section web")}\` to store it, or set MINIMAX_CODE_PLAN_KEY, MINIMAX_CODING_API_KEY, MINIMAX_OAUTH_TOKEN, or MINIMAX_API_KEY in the Gateway environment.`,
|
||||
docs: "https://docs.openclaw.ai/tools/web",
|
||||
};
|
||||
}
|
||||
|
||||
@@ -13,12 +13,14 @@ describe("minimax web search provider", () => {
|
||||
const originalApiHost = process.env.MINIMAX_API_HOST;
|
||||
const originalCodePlanKey = process.env.MINIMAX_CODE_PLAN_KEY;
|
||||
const originalCodingApiKey = process.env.MINIMAX_CODING_API_KEY;
|
||||
const originalOauthToken = process.env.MINIMAX_OAUTH_TOKEN;
|
||||
const originalApiKey = process.env.MINIMAX_API_KEY;
|
||||
|
||||
beforeEach(() => {
|
||||
delete process.env.MINIMAX_API_HOST;
|
||||
delete process.env.MINIMAX_CODE_PLAN_KEY;
|
||||
delete process.env.MINIMAX_CODING_API_KEY;
|
||||
delete process.env.MINIMAX_OAUTH_TOKEN;
|
||||
delete process.env.MINIMAX_API_KEY;
|
||||
});
|
||||
|
||||
@@ -26,6 +28,7 @@ describe("minimax web search provider", () => {
|
||||
process.env.MINIMAX_API_HOST = originalApiHost;
|
||||
process.env.MINIMAX_CODE_PLAN_KEY = originalCodePlanKey;
|
||||
process.env.MINIMAX_CODING_API_KEY = originalCodingApiKey;
|
||||
process.env.MINIMAX_OAUTH_TOKEN = originalOauthToken;
|
||||
process.env.MINIMAX_API_KEY = originalApiKey;
|
||||
});
|
||||
|
||||
@@ -130,7 +133,7 @@ describe("minimax web search provider", () => {
|
||||
expect(resolveMiniMaxApiKey({ apiKey: "configured-key" })).toBe("configured-key");
|
||||
});
|
||||
|
||||
it("accepts MINIMAX_CODING_API_KEY as a coding-plan alias", () => {
|
||||
it("accepts MINIMAX_CODING_API_KEY as a token-plan alias", () => {
|
||||
process.env.MINIMAX_CODING_API_KEY = "coding-key";
|
||||
expect(resolveMiniMaxApiKey()).toBe("coding-key");
|
||||
});
|
||||
@@ -139,6 +142,12 @@ describe("minimax web search provider", () => {
|
||||
process.env.MINIMAX_API_KEY = "plain-key";
|
||||
expect(resolveMiniMaxApiKey()).toBe("plain-key");
|
||||
});
|
||||
|
||||
it("accepts MINIMAX_OAUTH_TOKEN before the legacy API-key fallback", () => {
|
||||
process.env.MINIMAX_OAUTH_TOKEN = "oauth-token";
|
||||
process.env.MINIMAX_API_KEY = "plain-key";
|
||||
expect(resolveMiniMaxApiKey()).toBe("oauth-token");
|
||||
});
|
||||
});
|
||||
|
||||
describe("endpoint constants", () => {
|
||||
|
||||
@@ -4,7 +4,11 @@ import {
|
||||
} from "openclaw/plugin-sdk/provider-web-search-config-contract";
|
||||
|
||||
const MINIMAX_CREDENTIAL_PATH = "plugins.entries.minimax.config.webSearch.apiKey";
|
||||
const MINIMAX_CODING_PLAN_ENV_VARS = ["MINIMAX_CODE_PLAN_KEY", "MINIMAX_CODING_API_KEY"] as const;
|
||||
const MINIMAX_TOKEN_PLAN_ENV_VARS = [
|
||||
"MINIMAX_CODE_PLAN_KEY",
|
||||
"MINIMAX_CODING_API_KEY",
|
||||
"MINIMAX_OAUTH_TOKEN",
|
||||
] as const;
|
||||
|
||||
type MiniMaxWebSearchRuntime = typeof import("./minimax-web-search-provider.runtime.js");
|
||||
|
||||
@@ -32,9 +36,9 @@ export function createMiniMaxWebSearchProvider(): WebSearchProviderPlugin {
|
||||
return {
|
||||
id: "minimax",
|
||||
label: "MiniMax Search",
|
||||
hint: "Structured results via MiniMax Coding Plan search API",
|
||||
credentialLabel: "MiniMax Coding Plan key",
|
||||
envVars: [...MINIMAX_CODING_PLAN_ENV_VARS],
|
||||
hint: "Structured results via MiniMax Token Plan search API",
|
||||
credentialLabel: "MiniMax Token Plan key or OAuth token",
|
||||
envVars: [...MINIMAX_TOKEN_PLAN_ENV_VARS],
|
||||
placeholder: "sk-cp-...",
|
||||
signupUrl: "https://platform.minimax.io/user-center/basic-information/interface-key",
|
||||
docsUrl: "https://docs.openclaw.ai/tools/minimax-search",
|
||||
|
||||
@@ -3,7 +3,11 @@ import {
|
||||
type WebSearchProviderPlugin,
|
||||
} from "openclaw/plugin-sdk/provider-web-search-config-contract";
|
||||
|
||||
const MINIMAX_CODING_PLAN_ENV_VARS = ["MINIMAX_CODE_PLAN_KEY", "MINIMAX_CODING_API_KEY"] as const;
|
||||
const MINIMAX_TOKEN_PLAN_ENV_VARS = [
|
||||
"MINIMAX_CODE_PLAN_KEY",
|
||||
"MINIMAX_CODING_API_KEY",
|
||||
"MINIMAX_OAUTH_TOKEN",
|
||||
] as const;
|
||||
|
||||
export function createMiniMaxWebSearchProvider(): WebSearchProviderPlugin {
|
||||
const credentialPath = "plugins.entries.minimax.config.webSearch.apiKey";
|
||||
@@ -11,9 +15,9 @@ export function createMiniMaxWebSearchProvider(): WebSearchProviderPlugin {
|
||||
return {
|
||||
id: "minimax",
|
||||
label: "MiniMax Search",
|
||||
hint: "Structured results via MiniMax Coding Plan search API",
|
||||
credentialLabel: "MiniMax Coding Plan key",
|
||||
envVars: [...MINIMAX_CODING_PLAN_ENV_VARS],
|
||||
hint: "Structured results via MiniMax Token Plan search API",
|
||||
credentialLabel: "MiniMax Token Plan key or OAuth token",
|
||||
envVars: [...MINIMAX_TOKEN_PLAN_ENV_VARS],
|
||||
placeholder: "sk-cp-...",
|
||||
signupUrl: "https://platform.minimax.io/user-center/basic-information/interface-key",
|
||||
docsUrl: "https://docs.openclaw.ai/tools/minimax-search",
|
||||
|
||||
@@ -76,7 +76,7 @@ const mockWebSearchProviders = [
|
||||
{
|
||||
id: "minimax",
|
||||
pluginId: "minimax",
|
||||
envVars: ["MINIMAX_CODE_PLAN_KEY", "MINIMAX_CODING_API_KEY"],
|
||||
envVars: ["MINIMAX_CODE_PLAN_KEY", "MINIMAX_CODING_API_KEY", "MINIMAX_OAUTH_TOKEN"],
|
||||
credentialPath: "plugins.entries.minimax.config.webSearch.apiKey",
|
||||
getCredentialValue: getScopedWebSearchCredential("minimax"),
|
||||
getConfiguredCredentialValue: getConfiguredPluginWebSearchCredential("minimax"),
|
||||
@@ -421,6 +421,7 @@ describe("web search provider auto-detection", () => {
|
||||
delete process.env.MINIMAX_API_KEY;
|
||||
delete process.env.MINIMAX_CODE_PLAN_KEY;
|
||||
delete process.env.MINIMAX_CODING_API_KEY;
|
||||
delete process.env.MINIMAX_OAUTH_TOKEN;
|
||||
delete process.env.MOONSHOT_API_KEY;
|
||||
delete process.env.PERPLEXITY_API_KEY;
|
||||
delete process.env.OPENROUTER_API_KEY;
|
||||
@@ -475,6 +476,11 @@ describe("web search provider auto-detection", () => {
|
||||
expect(resolveSearchProvider({})).toBe("minimax");
|
||||
});
|
||||
|
||||
it("auto-detects minimax when only MINIMAX_OAUTH_TOKEN is set", () => {
|
||||
process.env.MINIMAX_OAUTH_TOKEN = "oauth-test-token"; // pragma: allowlist secret
|
||||
expect(resolveSearchProvider({})).toBe("minimax");
|
||||
});
|
||||
|
||||
it("auto-detects perplexity when only PERPLEXITY_API_KEY is set", () => {
|
||||
process.env.PERPLEXITY_API_KEY = "test-perplexity-key"; // pragma: allowlist secret
|
||||
expect(resolveSearchProvider({})).toBe("perplexity");
|
||||
|
||||
Reference in New Issue
Block a user