feat: add MiniMax OAuth plugin (#4521) (thanks @Maosghoul)

This commit is contained in:
Peter Steinberger
2026-01-31 12:42:45 +01:00
parent b9b94715fa
commit 1287328b6f
21 changed files with 795 additions and 38 deletions

View File

@@ -14,6 +14,7 @@ const log = createSubsystemLogger("agents/auth-profiles");
const CLAUDE_CLI_CREDENTIALS_RELATIVE_PATH = ".claude/.credentials.json";
const CODEX_CLI_AUTH_FILENAME = "auth.json";
const QWEN_CLI_CREDENTIALS_RELATIVE_PATH = ".qwen/oauth_creds.json";
const MINIMAX_CLI_CREDENTIALS_RELATIVE_PATH = ".minimax/oauth_creds.json";
const CLAUDE_CLI_KEYCHAIN_SERVICE = "Claude Code-credentials";
const CLAUDE_CLI_KEYCHAIN_ACCOUNT = "Claude Code";
@@ -27,11 +28,13 @@ type CachedValue<T> = {
let claudeCliCache: CachedValue<ClaudeCliCredential> | null = null;
let codexCliCache: CachedValue<CodexCliCredential> | null = null;
let qwenCliCache: CachedValue<QwenCliCredential> | null = null;
let minimaxCliCache: CachedValue<MiniMaxCliCredential> | null = null;
export function resetCliCredentialCachesForTest(): void {
claudeCliCache = null;
codexCliCache = null;
qwenCliCache = null;
minimaxCliCache = null;
}
export type ClaudeCliCredential =
@@ -66,6 +69,14 @@ export type QwenCliCredential = {
expires: number;
};
export type MiniMaxCliCredential = {
type: "oauth";
provider: "minimax-portal";
access: string;
refresh: string;
expires: number;
};
type ClaudeCliFileOptions = {
homeDir?: string;
};
@@ -102,6 +113,11 @@ function resolveQwenCliCredentialsPath(homeDir?: string) {
return path.join(baseDir, QWEN_CLI_CREDENTIALS_RELATIVE_PATH);
}
function resolveMiniMaxCliCredentialsPath(homeDir?: string) {
const baseDir = homeDir ?? resolveUserPath("~");
return path.join(baseDir, MINIMAX_CLI_CREDENTIALS_RELATIVE_PATH);
}
function computeCodexKeychainAccount(codexHome: string) {
const hash = createHash("sha256").update(codexHome).digest("hex");
return `cli|${hash.slice(0, 16)}`;
@@ -200,6 +216,36 @@ function readQwenCliCredentials(options?: { homeDir?: string }): QwenCliCredenti
};
}
function readMiniMaxCliCredentials(options?: { homeDir?: string }): MiniMaxCliCredential | null {
const credPath = resolveMiniMaxCliCredentialsPath(options?.homeDir);
const raw = loadJsonFile(credPath);
if (!raw || typeof raw !== "object") {
return null;
}
const data = raw as Record<string, unknown>;
const accessToken = data.access_token;
const refreshToken = data.refresh_token;
const expiresAt = data.expiry_date;
if (typeof accessToken !== "string" || !accessToken) {
return null;
}
if (typeof refreshToken !== "string" || !refreshToken) {
return null;
}
if (typeof expiresAt !== "number" || !Number.isFinite(expiresAt)) {
return null;
}
return {
type: "oauth",
provider: "minimax-portal",
access: accessToken,
refresh: refreshToken,
expires: expiresAt,
};
}
function readClaudeCliKeychainCredentials(
execSyncImpl: ExecSyncFn = execSync,
): ClaudeCliCredential | null {
@@ -539,3 +585,25 @@ export function readQwenCliCredentialsCached(options?: {
}
return value;
}
export function readMiniMaxCliCredentialsCached(options?: {
ttlMs?: number;
homeDir?: string;
}): MiniMaxCliCredential | null {
const ttlMs = options?.ttlMs ?? 0;
const now = Date.now();
const cacheKey = resolveMiniMaxCliCredentialsPath(options?.homeDir);
if (
ttlMs > 0 &&
minimaxCliCache &&
minimaxCliCache.cacheKey === cacheKey &&
now - minimaxCliCache.readAt < ttlMs
) {
return minimaxCliCache.value;
}
const value = readMiniMaxCliCredentials({ homeDir: options?.homeDir });
if (ttlMs > 0) {
minimaxCliCache = { value, readAt: now, cacheKey };
}
return value;
}