Files
claudecodeui/server/modules/providers/tests/opencode-models.test.ts
2026-07-01 23:32:13 +03:00

136 lines
3.5 KiB
TypeScript

import assert from 'node:assert/strict';
import test from 'node:test';
import {
buildOpenCodeDefinitionFromVerboseModels,
buildOpenCodeDefinitionFromIds,
parseOpenCodeModelsStdout,
parseOpenCodeVerboseModelsStdout,
} from '@/modules/providers/list/opencode/opencode-models.provider.js';
test('OpenCode models provider parses plain CLI output and removes duplicates', () => {
const ids = parseOpenCodeModelsStdout(`
opencode/big-pickle
not a model
anthropic/claude-opus-4-7-fast
anthropic/claude-opus-4-7-fast
openai/gpt-5.5-pro
`);
assert.deepEqual(ids, [
'opencode/big-pickle',
'anthropic/claude-opus-4-7-fast',
'openai/gpt-5.5-pro',
]);
});
test('OpenCode models provider formats frontend labels from provider-prefixed ids', () => {
const definition = buildOpenCodeDefinitionFromIds([
'opencode/deepseek-v4-flash-free',
'opencode/nemotron-3-super-free',
'anthropic/claude-3-5-sonnet-20241022',
'anthropic/claude-opus-4-7-fast',
'openai/gpt-5.4-mini-fast',
'openai/gpt-5.5-pro',
'newprovider/alpha-v12-special-20261231',
]);
assert.deepEqual(definition.OPTIONS, [
{
value: 'opencode/deepseek-v4-flash-free',
label: 'Deepseek V4 Flash Free',
description: 'opencode - opencode/deepseek-v4-flash-free',
},
{
value: 'opencode/nemotron-3-super-free',
label: 'Nemotron 3 Super Free',
description: 'opencode - opencode/nemotron-3-super-free',
},
{
value: 'anthropic/claude-3-5-sonnet-20241022',
label: 'Claude 3.5 Sonnet (2024-10-22)',
description: 'anthropic - anthropic/claude-3-5-sonnet-20241022',
},
{
value: 'anthropic/claude-opus-4-7-fast',
label: 'Claude Opus 4.7 Fast',
description: 'anthropic - anthropic/claude-opus-4-7-fast',
},
{
value: 'openai/gpt-5.4-mini-fast',
label: 'GPT-5.4 Mini Fast',
description: 'openai - openai/gpt-5.4-mini-fast',
},
{
value: 'openai/gpt-5.5-pro',
label: 'GPT-5.5 Pro',
description: 'openai - openai/gpt-5.5-pro',
},
{
value: 'newprovider/alpha-v12-special-20261231',
label: 'Alpha V12 Special (2026-12-31)',
description: 'newprovider - newprovider/alpha-v12-special-20261231',
},
]);
});
test('OpenCode models provider maps verbose model variants to effort options', () => {
const models = parseOpenCodeVerboseModelsStdout(`
opencode/deepseek-v4-flash-free
{
"id": "deepseek-v4-flash-free",
"providerID": "opencode",
"name": "DeepSeek V4 Flash Free",
"variants": {
"low": {
"reasoningEffort": "low"
},
"high": {
"reasoningEffort": "high"
}
}
}
anthropic/claude-sonnet-5
{
"id": "claude-sonnet-5",
"providerID": "anthropic",
"name": "Claude Sonnet 5",
"variants": {
"low": {
"effort": "low"
},
"max": {
"effort": "max"
}
}
}
`);
const definition = buildOpenCodeDefinitionFromVerboseModels(models);
assert.deepEqual(definition.OPTIONS, [
{
value: 'opencode/deepseek-v4-flash-free',
label: 'DeepSeek V4 Flash Free',
description: 'opencode - opencode/deepseek-v4-flash-free',
effort: {
values: [
{ value: 'low' },
{ value: 'high' },
],
},
},
{
value: 'anthropic/claude-sonnet-5',
label: 'Claude Sonnet 5',
description: 'anthropic - anthropic/claude-sonnet-5',
effort: {
values: [
{ value: 'low' },
{ value: 'max' },
],
},
},
]);
});