Files
openmaic/OpenMAIC/tests/ai/model-metadata.test.ts
2026-08-16 14:58:47 +08:00

83 lines
3.0 KiB
TypeScript

import { describe, expect, it } from 'vitest';
import { PROVIDERS } from '@/lib/ai/providers';
import { getCatalogThinkingCapability, getModelMetadataKey } from '@/lib/ai/model-metadata';
import type { ProviderConfig, ProviderId } from '@/lib/types/provider';
// These models intentionally do not expose a configurable thinking control.
const MODELS_WITHOUT_CONFIGURABLE_THINKING = new Set<string>([
// Bedrock models can reason, but this provider intentionally does not expose
// thinking controls yet. Those require Bedrock-specific request serialization
// (`providerOptions.bedrock.reasoningConfig`), which is outside this text-provider
// rebase and belongs in the maintainer's follow-up request-serialization review.
'bedrock:us.anthropic.claude-sonnet-5',
'bedrock:us.anthropic.claude-opus-4-8',
'bedrock:us.anthropic.claude-opus-4-7',
'bedrock:us.anthropic.claude-sonnet-4-6',
'bedrock:us.amazon.nova-pro-v1:0',
'bedrock:us.amazon.nova-lite-v1:0',
'bedrock:us.amazon.nova-micro-v1:0',
'bedrock:us.meta.llama3-3-70b-instruct-v1:0',
'siliconflow:Pro/moonshotai/Kimi-K2.5',
'grok:grok-4.20',
'grok:grok-4-1-fast-non-reasoning',
'grok:grok-code-fast-1',
'atlascloud:qwen/qwen3.5-flash',
'ollama:llama3.3',
'ollama:gemma3',
'ollama:deepseek-r1',
]);
function findDriftedModels(providers: Record<ProviderId, ProviderConfig>): string[] {
const driftedModels: string[] = [];
for (const provider of Object.values(providers)) {
for (const model of provider.models) {
const key = getModelMetadataKey(provider.id, model.id);
if (getCatalogThinkingCapability(provider.id, model.id)) {
continue;
}
if (MODELS_WITHOUT_CONFIGURABLE_THINKING.has(key)) {
continue;
}
driftedModels.push(key);
}
}
return driftedModels;
}
describe('model metadata thinking capabilities', () => {
it('accounts for every PROVIDERS model with a capability or explicit non-thinking allowlist', () => {
expect(findDriftedModels(PROVIDERS)).toEqual([]);
});
it('catches drift when a provider model has no thinking metadata or allowlist entry', () => {
const syntheticProviders = {
siliconflow: {
...PROVIDERS.siliconflow,
models: [
...PROVIDERS.siliconflow.models,
{ id: '__synthetic_missing__', name: 'x', capabilities: {} },
],
},
} as Record<ProviderId, ProviderConfig>;
expect(findDriftedModels(syntheticProviders)).toContain('siliconflow:__synthetic_missing__');
});
it('resolves thinking capabilities for the previously missing explicit models', () => {
expect(getCatalogThinkingCapability('siliconflow', 'deepseek-ai/DeepSeek-V3.2')).toBeDefined();
expect(getCatalogThinkingCapability('lemonade', 'Gemma-4-26B-A4B-it-GGUF')).toBeDefined();
});
it('resolves GPT-5.6 Sol alias metadata through the canonical model ID', () => {
expect(getCatalogThinkingCapability('openai', 'gpt-5.6-sol')).toEqual(
getCatalogThinkingCapability('openai', 'gpt-5.6'),
);
});
});