mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-17 08:20:45 +00:00
fix(minimax): resolve portal OAuth token via resolveProviderAuth with oauthMarker (#79731)
Root cause: resolvePortalCatalog manually called ensureAuthProfileStore +
listProfilesForProvider to detect OAuth profiles, then returned the raw
MINIMAX_OAUTH_MARKER string as the catalog apiKey. The request layer has
no handler for the marker string — it reached the provider as a literal
API key value, causing "No API key found" even with valid OAuth tokens.
Fix: use ctx.resolveProviderAuth(PORTAL_PROVIDER_ID, { oauthMarker })
matching the pattern used by the chutes extension. The resolver returns
the marker when an OAuth profile exists, which the request layer correctly
intercepts and replaces with the live access token.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
committed by
Radek Sienkiewicz
parent
0120fd3a60
commit
39953ab72a
@@ -4,6 +4,7 @@ import {
|
||||
registerProviderPlugin,
|
||||
requireRegisteredProvider,
|
||||
} from "openclaw/plugin-sdk/plugin-test-runtime";
|
||||
import { MINIMAX_OAUTH_MARKER } from "openclaw/plugin-sdk/provider-auth";
|
||||
import { describe, expect, it, vi } from "vitest";
|
||||
import { registerMinimaxProviders } from "./provider-registration.js";
|
||||
import { createMiniMaxWebSearchProvider } from "./src/minimax-web-search-provider.js";
|
||||
@@ -325,6 +326,33 @@ describe("minimax provider hooks", () => {
|
||||
expect(result?.windows).toEqual([{ label: "5h", usedPercent: 2, resetAt: undefined }]);
|
||||
});
|
||||
|
||||
it("portal catalog resolves OAuth token via resolveProviderAuth with oauthMarker", async () => {
|
||||
const { providers } = await registerProviderPlugin({
|
||||
plugin: minimaxProviderPlugin,
|
||||
id: "minimax",
|
||||
name: "MiniMax Provider",
|
||||
});
|
||||
const portalProvider = requireRegisteredProvider(providers, "minimax-portal");
|
||||
const resolveProviderAuth = vi.fn(() => ({
|
||||
apiKey: MINIMAX_OAUTH_MARKER,
|
||||
mode: "oauth" as const,
|
||||
source: "profile" as const,
|
||||
}));
|
||||
const result = await portalProvider.catalog?.run({
|
||||
config: {},
|
||||
resolveProviderAuth,
|
||||
resolveProviderApiKey: () => ({ apiKey: undefined }),
|
||||
} as never);
|
||||
|
||||
expect(resolveProviderAuth).toHaveBeenCalledWith("minimax-portal", {
|
||||
oauthMarker: MINIMAX_OAUTH_MARKER,
|
||||
});
|
||||
expect(result).not.toBeNull();
|
||||
if (result && "provider" in result) {
|
||||
expect(result.provider.apiKey).toBe(MINIMAX_OAUTH_MARKER);
|
||||
}
|
||||
});
|
||||
|
||||
it("writes api and authHeader into the MiniMax portal OAuth config patch", async () => {
|
||||
const { providers } = await registerProviderPlugin({
|
||||
plugin: minimaxProviderPlugin,
|
||||
|
||||
@@ -6,11 +6,7 @@ import type {
|
||||
ProviderAuthResult,
|
||||
ProviderCatalogContext,
|
||||
} from "openclaw/plugin-sdk/plugin-entry";
|
||||
import {
|
||||
MINIMAX_OAUTH_MARKER,
|
||||
ensureAuthProfileStore,
|
||||
listProfilesForProvider,
|
||||
} from "openclaw/plugin-sdk/provider-auth";
|
||||
import { MINIMAX_OAUTH_MARKER } from "openclaw/plugin-sdk/provider-auth";
|
||||
import { buildOauthProviderAuthResult } from "openclaw/plugin-sdk/provider-auth";
|
||||
import { createProviderApiKeyAuthMethod } from "openclaw/plugin-sdk/provider-auth-api-key";
|
||||
import { buildProviderReplayFamilyHooks } from "openclaw/plugin-sdk/provider-model-shared";
|
||||
@@ -100,13 +96,13 @@ function resolveApiCatalog(ctx: ProviderCatalogContext) {
|
||||
|
||||
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 = normalizeOptionalString(explicitProvider?.apiKey);
|
||||
const apiKey = envApiKey ?? explicitApiKey ?? (hasProfiles ? MINIMAX_OAUTH_MARKER : undefined);
|
||||
// resolveProviderAuth handles OAuth profiles via oauthMarker, returning the
|
||||
// sentinel so the request layer can swap in the live access token (#79731).
|
||||
const { apiKey: profileApiKey } = ctx.resolveProviderAuth(PORTAL_PROVIDER_ID, {
|
||||
oauthMarker: MINIMAX_OAUTH_MARKER,
|
||||
});
|
||||
const apiKey = explicitApiKey ?? profileApiKey;
|
||||
if (!apiKey) {
|
||||
return null;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user