fix: format opencode model catalog labels

OpenCode returns provider-prefixed ids directly from the CLI. Passing those ids through as
labels made the model picker hard to scan: users saw values like
anthropic/claude-3-5-sonnet-20241022 or lowercased, hyphen-split text instead
of readable model names.

Keep the exact OpenCode id as the option value because that is what the CLI
expects, but derive a presentation label for the frontend. The formatter is
intentionally generic rather than a catalog of known providers. It handles common
identifier structure such as provider/model, hyphen-delimited words, v-prefixed
versions, adjacent numeric version tokens, and 8-digit date suffixes.

This keeps OpenCode usable as its model list expands across many upstream
providers without requiring code changes for every new provider or model family.
The description keeps the raw provider-prefixed id visible so users can still
confirm the precise model being selected.
This commit is contained in:
Haileyesus
2026-05-22 17:02:03 +03:00
parent 6ca0d38fa4
commit fe3a8580dc
2 changed files with 193 additions and 13 deletions

View File

@@ -0,0 +1,73 @@
import assert from 'node:assert/strict';
import test from 'node:test';
import {
buildOpenCodeDefinitionFromIds,
parseOpenCodeModelsStdout,
} 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',
},
]);
});