130 lines
4.3 KiB
TypeScript
130 lines
4.3 KiB
TypeScript
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
|
|
import { mkdirSync, readFileSync, rmSync, writeFileSync } from 'node:fs';
|
|
import { join } from 'node:path';
|
|
import { tmpdir } from 'node:os';
|
|
|
|
const modelDiagnosticsMocks = vi.hoisted(() => ({
|
|
config: {} as Record<string, unknown>,
|
|
writeOpenClawConfig: vi.fn(),
|
|
testOpenClawDir: '/tmp/clawx-tests/model-diagnostics-openclaw',
|
|
}));
|
|
|
|
vi.mock('@electron/utils/channel-config', () => ({
|
|
readOpenClawConfig: vi.fn(async () => modelDiagnosticsMocks.config),
|
|
writeOpenClawConfig: vi.fn(async (config: Record<string, unknown>) => {
|
|
modelDiagnosticsMocks.config = config;
|
|
modelDiagnosticsMocks.writeOpenClawConfig(config);
|
|
}),
|
|
}));
|
|
|
|
vi.mock('@electron/utils/paths', () => ({
|
|
getOpenClawConfigDir: () => modelDiagnosticsMocks.testOpenClawDir,
|
|
}));
|
|
|
|
vi.mock('@electron/utils/logger', () => ({
|
|
logger: {
|
|
info: vi.fn(),
|
|
warn: vi.fn(),
|
|
error: vi.fn(),
|
|
},
|
|
}));
|
|
|
|
function authProfilesPath(homeDir: string): string {
|
|
return join(homeDir, '.openclaw', 'agents', 'main', 'agent', 'auth-profiles.json');
|
|
}
|
|
|
|
describe('Yinian model diagnostics', () => {
|
|
const originalHome = process.env.HOME;
|
|
const testHome = join(tmpdir(), 'clawx-tests', 'model-diagnostics-home');
|
|
|
|
beforeEach(() => {
|
|
vi.resetModules();
|
|
vi.clearAllMocks();
|
|
process.env.HOME = testHome;
|
|
rmSync(testHome, { recursive: true, force: true });
|
|
rmSync(modelDiagnosticsMocks.testOpenClawDir, { recursive: true, force: true });
|
|
mkdirSync(join(testHome, '.openclaw', 'agents', 'main', 'agent'), { recursive: true });
|
|
mkdirSync(modelDiagnosticsMocks.testOpenClawDir, { recursive: true });
|
|
modelDiagnosticsMocks.config = {
|
|
models: {
|
|
providers: {
|
|
minimax: {
|
|
baseUrl: 'https://api.minimaxi.com/anthropic',
|
|
api: 'anthropic-messages',
|
|
timeoutSeconds: 30,
|
|
models: [{ id: 'MiniMax-M2.7' }],
|
|
},
|
|
},
|
|
pricing: {
|
|
enabled: true,
|
|
},
|
|
},
|
|
agents: {
|
|
defaults: {
|
|
model: {
|
|
primary: 'minimax/MiniMax-M2.7',
|
|
fallbacks: ['minimax/MiniMax-M2.5'],
|
|
},
|
|
},
|
|
},
|
|
};
|
|
writeFileSync(authProfilesPath(testHome), JSON.stringify({
|
|
version: 1,
|
|
profiles: {
|
|
'minimax-cn:default': {
|
|
type: 'api_key',
|
|
provider: 'minimax-cn',
|
|
key: 'secret',
|
|
},
|
|
},
|
|
}, null, 2));
|
|
});
|
|
|
|
afterEach(() => {
|
|
process.env.HOME = originalHome;
|
|
rmSync(testHome, { recursive: true, force: true });
|
|
rmSync(modelDiagnosticsMocks.testOpenClawDir, { recursive: true, force: true });
|
|
});
|
|
|
|
it('repairs runtime model defaults and normalizes MiniMax auth profile aliases', async () => {
|
|
const {
|
|
buildYinianModelConfigDiagnostics,
|
|
ensureYinianModelRuntimeConfigured,
|
|
} = await import('@electron/utils/model-diagnostics');
|
|
|
|
await ensureYinianModelRuntimeConfigured();
|
|
|
|
expect(modelDiagnosticsMocks.writeOpenClawConfig).toHaveBeenCalledWith(expect.objectContaining({
|
|
models: expect.objectContaining({
|
|
pricing: expect.objectContaining({ enabled: false }),
|
|
providers: expect.objectContaining({
|
|
minimax: expect.objectContaining({ timeoutSeconds: 300 }),
|
|
}),
|
|
}),
|
|
agents: expect.objectContaining({
|
|
defaults: expect.objectContaining({
|
|
heartbeat: expect.objectContaining({ every: '0m' }),
|
|
}),
|
|
}),
|
|
}));
|
|
|
|
const authStore = JSON.parse(readFileSync(authProfilesPath(testHome), 'utf8')) as {
|
|
profiles: Record<string, { provider?: string; key?: string }>;
|
|
order?: Record<string, string[]>;
|
|
lastGood?: Record<string, string>;
|
|
};
|
|
expect(authStore.profiles['minimax:default']).toMatchObject({
|
|
provider: 'minimax',
|
|
key: 'secret',
|
|
});
|
|
expect(authStore.order?.minimax).toContain('minimax:default');
|
|
expect(authStore.lastGood?.minimax).toBe('minimax:default');
|
|
|
|
const diagnostics = await buildYinianModelConfigDiagnostics();
|
|
expect(diagnostics.ok).toBe(true);
|
|
expect(diagnostics.model.primary).toBe('minimax/MiniMax-M2.7');
|
|
expect(diagnostics.runtime.pricingCatalogFetchDisabled).toBe(true);
|
|
expect(diagnostics.checks.find((check) => check.id === 'auth-profile')?.status).toBe('ok');
|
|
});
|
|
});
|