fix(minimax): use account oauth endpoints

Routes MiniMax OAuth device-code and token polling directly to account-hosted OAuth2 endpoints for global and CN regions, avoiding guarded-fetch cross-origin redirect body stripping. Keeps provider API base URLs unchanged and adds regression coverage for both endpoint pairs.

Proof: local minimax OAuth tests, oxfmt check, lint, autoreview clean, official MiniMax CLI/source check, live MiniMax endpoint probes, and CI run 26729242892 on 6bfe20eb06.

Co-authored-by: Matt Schleder <schledermatthew@gmail.com>
This commit is contained in:
Matthew Schleder
2026-05-31 20:44:41 -04:00
committed by GitHub
parent 82d24b26ea
commit 6a96058f50
2 changed files with 66 additions and 3 deletions

View File

@@ -29,6 +29,67 @@ describe("normalizeOAuthExpires", () => {
});
describe("loginMiniMaxPortalOAuth", () => {
it("uses MiniMax account OAuth endpoints directly for global and CN login", async () => {
for (const [region, expectedHosts] of [
[
"global",
[
"https://account.minimax.io/oauth2/device/code",
"https://account.minimax.io/oauth2/token",
],
],
[
"cn",
[
"https://account.minimaxi.com/oauth2/device/code",
"https://account.minimaxi.com/oauth2/token",
],
],
] as const) {
const requestedUrls: string[] = [];
const fetchMock = vi.fn(async (input: RequestInfo | URL, init?: RequestInit) => {
requestedUrls.push(input instanceof Request ? input.url : String(input));
const body =
init?.body instanceof URLSearchParams
? init.body
: new URLSearchParams(typeof init?.body === "string" ? init.body : "");
if (requestedUrls.length === 1) {
return new Response(
JSON.stringify({
user_code: "CODE",
verification_uri: "https://example.com/device",
expired_in: Date.now() + 10_000,
state: body.get("state"),
}),
{ status: 200, headers: { "Content-Type": "application/json" } },
);
}
return new Response(
JSON.stringify({
status: "success",
access_token: "access",
refresh_token: "refresh",
expired_in: 3600,
}),
{ status: 200, headers: { "Content-Type": "application/json" } },
);
});
vi.stubGlobal("fetch", fetchMock);
await expect(
loginMiniMaxPortalOAuth({
region,
openUrl: vi.fn(async () => undefined),
note: vi.fn(async () => undefined),
progress: { update: vi.fn(), stop: vi.fn() },
}),
).resolves.toMatchObject({ access: "access", refresh: "refresh" });
expect(requestedUrls).toEqual(expectedHosts);
vi.unstubAllGlobals();
}
});
it("rejects Date-invalid authorization expiries before formatting instructions", async () => {
const fetchMock = vi.fn(async (_input: RequestInfo | URL, init?: RequestInit) => {
const body =

View File

@@ -14,10 +14,12 @@ export type MiniMaxRegion = "cn" | "global";
const MINIMAX_OAUTH_CONFIG = {
cn: {
baseUrl: "https://api.minimaxi.com",
oauthBaseUrl: "https://account.minimaxi.com",
clientId: "78257093-7e40-4613-99e0-527b14b39113",
},
global: {
baseUrl: "https://api.minimax.io",
oauthBaseUrl: "https://account.minimax.io",
clientId: "78257093-7e40-4613-99e0-527b14b39113",
},
} as const;
@@ -30,11 +32,11 @@ const MINIMAX_ABSOLUTE_EXPIRY_MS_THRESHOLD = 1_000_000_000_000;
function getOAuthEndpoints(region: MiniMaxRegion) {
const config = MINIMAX_OAUTH_CONFIG[region];
return {
codeEndpoint: `${config.baseUrl}/oauth/code`,
tokenEndpoint: `${config.baseUrl}/oauth/token`,
codeEndpoint: `${config.oauthBaseUrl}/oauth2/device/code`,
tokenEndpoint: `${config.oauthBaseUrl}/oauth2/token`,
clientId: config.clientId,
baseUrl: config.baseUrl,
hostname: new URL(config.baseUrl).hostname,
hostname: new URL(config.oauthBaseUrl).hostname,
};
}