Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/config/loader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ export function loadConfig(flags: GlobalFlags): Config {
const baseUrl = flags.baseUrl
|| process.env.MINIMAX_BASE_URL
|| file.base_url
|| file.oauth?.resource_url
|| (!apiKey ? file.oauth?.resource_url : undefined)
|| REGIONS[region]
|| REGIONS.global;

Expand Down
49 changes: 49 additions & 0 deletions test/config/loader.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { join } from 'path';
import { tmpdir } from 'os';
import { loadConfig, renameWithCrossDeviceFallback, writeConfigFile } from '../../src/config/loader';
import { CLIError } from '../../src/errors/base';
import { resolveCredential } from '../../src/auth/resolver';
import type { GlobalFlags } from '../../src/types/flags';

const baseFlags: GlobalFlags = {
Expand Down Expand Up @@ -58,6 +59,54 @@ describe('loadConfig', () => {
});
});

describe('OAuth resource URL credential scope', () => {
const testDir = join(tmpdir(), `mmx-oauth-host-test-${Date.now()}`);
const envKeys = ['MMX_CONFIG_DIR', 'MINIMAX_REGION', 'MINIMAX_BASE_URL'] as const;
let savedEnv: Array<string | undefined>;

beforeEach(async () => {
savedEnv = envKeys.map(key => process.env[key]);
for (const key of envKeys) delete process.env[key];
process.env.MMX_CONFIG_DIR = testDir;
await writeConfigFile({
region: 'cn',
api_key: 'file-key',
oauth: {
access_token: 'oauth-token',
refresh_token: 'refresh-token',
expires_at: '2099-01-01T00:00:00Z',
region: 'cn',
resource_url: 'https://oauth-resource.example',
},
});
});

afterEach(() => {
envKeys.forEach((key, index) => {
if (savedEnv[index] === undefined) delete process.env[key];
else process.env[key] = savedEnv[index];
});
rmSync(testDir, { recursive: true, force: true });
});

it.each(['global', 'cn'])('uses the %s API host when an explicit key overrides OAuth', async region => {
const config = loadConfig({ ...baseFlags, apiKey: 'flag-key', region });
expect(await resolveCredential(config)).toMatchObject({ token: 'flag-key', method: 'api-key' });
expect(config.baseUrl).toBe(region === 'cn' ? 'https://api.minimax.cn' : 'https://api.minimax.io');
});

it('keeps the resource URL when OAuth wins over a stored API key', async () => {
const config = loadConfig(baseFlags);
expect(await resolveCredential(config)).toMatchObject({ token: 'oauth-token', method: 'oauth' });
expect(config.baseUrl).toBe('https://oauth-resource.example');
});

it('preserves an explicit base URL with an explicit key', () => {
const config = loadConfig({ ...baseFlags, apiKey: 'flag-key', baseUrl: 'https://custom.example' });
expect(config.baseUrl).toBe('https://custom.example');
});
});

describe('writeConfigFile', () => {
const testDir = join(tmpdir(), `mmx-config-write-test-${Date.now()}`);
const originalConfigDir = process.env.MMX_CONFIG_DIR;
Expand Down