W / test /models-catalog-correctness.test.js
Ac66's picture
Upload folder using huggingface_hub
2b64d42 verified
import { describe, it } from 'node:test';
import assert from 'node:assert/strict';
import {
MODELS,
resolveModel,
getModelInfo,
mergeCloudModels,
} from '../src/models.js';
describe('v2.0.29 model catalog correctness', () => {
it('maps opus-4.7 shorthand aliases to canonical 4.7 medium keys', () => {
assert.equal(resolveModel('opus-4.7'), 'claude-opus-4-7-medium');
assert.equal(resolveModel('o4.7'), 'claude-opus-4-7-medium');
assert.equal(resolveModel('claude-opus-4.7'), 'claude-opus-4-7-medium');
});
it('maps opus-4.7 thinking aliases to medium-thinking canonical key', () => {
assert.equal(resolveModel('opus-4.7-thinking'), 'claude-opus-4-7-medium-thinking');
assert.equal(resolveModel('claude-opus-4.7-thinking'), 'claude-opus-4-7-medium-thinking');
assert.equal(resolveModel('claude-opus-4.7-high-thinking'), 'claude-opus-4-7-high-thinking');
});
it('keeps new v2.0.29 model metadata aligned with declared keys', () => {
assert.equal(getModelInfo('kimi-k2-thinking')?.modelUid, 'MODEL_KIMI_K2_THINKING');
assert.equal(getModelInfo('kimi-k2-thinking')?.enumValue, 394);
assert.equal(getModelInfo('kimi-k2-thinking')?.credit, 1);
assert.equal(getModelInfo('glm-4.7-fast')?.enumValue, 418);
assert.equal(getModelInfo('glm-4.7-fast')?.modelUid, 'MODEL_GLM_4_7_FAST');
});
it('validates swe and minimax enum updates from release payload', () => {
assert.equal(getModelInfo('swe-1.5-thinking')?.enumValue, 369);
assert.equal(getModelInfo('swe-1.5')?.enumValue, 377);
assert.equal(getModelInfo('swe-1.6')?.enumValue, 420);
assert.equal(getModelInfo('swe-1.6-fast')?.enumValue, 421);
assert.equal(getModelInfo('minimax-m2.5')?.enumValue, 419);
assert.equal(getModelInfo('minimax-m2.5')?.modelUid, 'MODEL_MINIMAX_M2_1');
});
it('supports adaptive as explicit model for dynamic routing', () => {
assert.equal(resolveModel('adaptive'), 'adaptive');
assert.equal(getModelInfo('adaptive')?.enumValue, 0);
assert.equal(getModelInfo('adaptive')?.credit, 1);
});
// GPT-5.5 + Opus 4.7 max showed up in the live GetCascadeModelConfigs response
// on 2026-04-30. They were exposed implicitly through mergeCloudModels with
// ugly hyphenated names; the explicit catalog entries make the dotted aliases
// (gpt-5.5-medium, claude-opus-4.7-max) work and pin curated credit values.
it('exposes gpt-5.5 ladder with cloud-format aliases', () => {
for (const tier of ['none', 'low', 'medium', 'high', 'xhigh']) {
assert.ok(getModelInfo(`gpt-5.5-${tier}`), `gpt-5.5-${tier} missing`);
// cloud sends `gpt-5-5-${tier}`, we should resolve it back
assert.equal(resolveModel(`gpt-5-5-${tier}`), `gpt-5.5-${tier}`);
// priority lane (=fast)
assert.equal(
resolveModel(`gpt-5-5-${tier}-priority`),
`gpt-5.5-${tier}-fast`,
);
}
assert.equal(resolveModel('gpt-5.5'), 'gpt-5.5-medium');
assert.equal(resolveModel('gpt-5-5'), 'gpt-5.5-medium');
assert.equal(getModelInfo('gpt-5.5-medium')?.modelUid, 'gpt-5-5-medium');
});
it('exposes claude-opus-4-7-max with dotted alias', () => {
assert.ok(getModelInfo('claude-opus-4-7-max'));
assert.equal(resolveModel('claude-opus-4.7-max'), 'claude-opus-4-7-max');
assert.equal(getModelInfo('claude-opus-4-7-max')?.modelUid, 'claude-opus-4-7-max');
});
// sub2api end-to-end test (v2.0.51) caught these — `gpt-5.2-medium` 400'd
// because the catalog only had bare `gpt-5.2`. Same shape for 5.4 (had tiers
// but no bare) and 5.3-codex (had bare but no -medium dotted alias).
it('cross-tier aliases resolve regardless of which side is canonical', () => {
assert.equal(resolveModel('gpt-5.2-medium'), 'gpt-5.2');
assert.equal(resolveModel('gpt-5-2-medium'), 'gpt-5.2');
assert.equal(resolveModel('gpt-5.4'), 'gpt-5.4-medium');
assert.equal(resolveModel('gpt-5.3-codex-medium'), 'gpt-5.3-codex');
assert.equal(resolveModel('gpt-5.2-codex'), 'gpt-5.2-codex-medium');
// Non-existent tier should still fall through to itself (not silently route)
assert.equal(resolveModel('gpt-5.2-notarealtier'), 'gpt-5.2-notarealtier');
});
it('exposes gpt-5.3-codex tier ladder (low/high/xhigh + priority lane)', () => {
assert.ok(getModelInfo('gpt-5.3-codex-low'));
assert.ok(getModelInfo('gpt-5.3-codex-high'));
assert.ok(getModelInfo('gpt-5.3-codex-xhigh'));
assert.equal(resolveModel('gpt-5-3-codex-low'), 'gpt-5.3-codex-low');
assert.equal(resolveModel('gpt-5-3-codex-medium'), 'gpt-5.3-codex'); // bare = legacy alias
assert.equal(resolveModel('gpt-5-3-codex-high-priority'), 'gpt-5.3-codex-high-fast');
});
it('mergeCloudModels should skip already-known model UIDs (dedupe path)', () => {
const before = Object.keys(MODELS).length;
const dynamicUid = 'NEW_MODEL_4_7_TEST';
const dynamicKey = dynamicUid.toLowerCase().replace(/_/g, '-');
const added = mergeCloudModels([
{ provider: 'MODEL_PROVIDER_OPENAI', modelUid: 'claude-opus-4-7-medium-thinking', creditMultiplier: 999 },
{ provider: 'MODEL_PROVIDER_OPENAI', modelUid: dynamicUid, creditMultiplier: 3 },
]);
const after = Object.keys(MODELS).length;
assert.equal(added, 1);
assert.equal(after - before, 1);
try {
assert.equal(getModelInfo(dynamicKey)?.credit, 3);
} finally {
if (MODELS[dynamicKey]) {
delete MODELS[dynamicKey];
}
}
});
});