feat(team): add Opus 4.8 to model catalog and runtime profile

Wire claude-opus-4-8 (+ [1m] variant) through the team model picker
alongside 4.7 and 4.6, point the opus alias label at 4.8, update the
reasoning/long-context predicates, and switch the fast-mode UI
message to mention 4.8.
This commit is contained in:
777genius 2026-05-29 00:54:33 +03:00
parent 37334aad0d
commit 6eada589aa
9 changed files with 43 additions and 11 deletions

View file

@ -95,6 +95,8 @@ function isKnownAnthropicReasoningModel(model: string | null | undefined): boole
return ( return (
normalized === 'opus' || normalized === 'opus' ||
normalized === 'sonnet' || normalized === 'sonnet' ||
normalized === 'claude-opus-4-8' ||
normalized.startsWith('claude-opus-4-8-') ||
normalized === 'claude-opus-4-7' || normalized === 'claude-opus-4-7' ||
normalized.startsWith('claude-opus-4-7-') || normalized.startsWith('claude-opus-4-7-') ||
normalized === 'claude-opus-4-6' || normalized === 'claude-opus-4-6' ||
@ -221,8 +223,8 @@ export function resolveAnthropicFastMode(params: {
'Fast mode is not supported by this Anthropic runtime.'; 'Fast mode is not supported by this Anthropic runtime.';
} else if (!params.selection.supportsFastMode) { } else if (!params.selection.supportsFastMode) {
disabledReason = params.selection.displayName disabledReason = params.selection.displayName
? `Fast mode is available only for Opus 4.6. Selected model resolves to ${params.selection.displayName}.` ? `Fast mode is available only for Opus 4.8. Selected model resolves to ${params.selection.displayName}.`
: 'Fast mode is available only for Opus 4.6.'; : 'Fast mode is available only for Opus 4.8.';
} else if (!params.selection.providerFastModeAvailable) { } else if (!params.selection.providerFastModeAvailable) {
disabledReason = disabledReason =
params.selection.providerFastModeReason ?? 'Fast mode is currently unavailable.'; params.selection.providerFastModeReason ?? 'Fast mode is currently unavailable.';

View file

@ -18,8 +18,9 @@ interface OptionalSettingsSectionProps {
const SUMMARY_PREFIXES_TO_STRIP = ['Provider:', 'Model:', 'Effort:', 'Worktree:']; const SUMMARY_PREFIXES_TO_STRIP = ['Provider:', 'Model:', 'Effort:', 'Worktree:'];
const MODEL_LABEL_OVERRIDES: Array<[RegExp, string]> = [ const MODEL_LABEL_OVERRIDES: Array<[RegExp, string]> = [
[/claude[-\s]?opus[-\s]?4[-\s]?6/i, 'Opus 4.6'], [/claude[-\s]?opus[-\s]?4[-\s]?8/i, 'Opus 4.8'],
[/claude[-\s]?opus[-\s]?4[-\s]?7/i, 'Opus 4.7'], [/claude[-\s]?opus[-\s]?4[-\s]?7/i, 'Opus 4.7'],
[/claude[-\s]?opus[-\s]?4[-\s]?6/i, 'Opus 4.6'],
[/claude[-\s]?opus[-\s]?4[-\s]?5/i, 'Opus 4.5'], [/claude[-\s]?opus[-\s]?4[-\s]?5/i, 'Opus 4.5'],
[/claude[-\s]?sonnet[-\s]?4[-\s]?6/i, 'Sonnet 4.6'], [/claude[-\s]?sonnet[-\s]?4[-\s]?6/i, 'Sonnet 4.6'],
[/claude[-\s]?sonnet[-\s]?4[-\s]?5/i, 'Sonnet 4.5'], [/claude[-\s]?sonnet[-\s]?4[-\s]?5/i, 'Sonnet 4.5'],

View file

@ -825,13 +825,13 @@ export const TeamModelSelector: React.FC<TeamModelSelectorProps> = ({
'anthropic', 'anthropic',
getAnthropicDefaultTeamModel(false), getAnthropicDefaultTeamModel(false),
runtimeProviderStatus runtimeProviderStatus
) ?? 'Opus 4.7 (1M)'; ) ?? 'Opus 4.8 (1M)';
const defaultLimitedContextModel = const defaultLimitedContextModel =
getRuntimeAwareProviderScopedTeamModelLabel( getRuntimeAwareProviderScopedTeamModelLabel(
'anthropic', 'anthropic',
getAnthropicDefaultTeamModel(true), getAnthropicDefaultTeamModel(true),
runtimeProviderStatus runtimeProviderStatus
) ?? 'Opus 4.7'; ) ?? 'Opus 4.8';
return t('modelSelector.defaultTooltip.anthropic', { return t('modelSelector.defaultTooltip.anthropic', {
longContextModel: defaultLongContextModel, longContextModel: defaultLongContextModel,

View file

@ -431,6 +431,13 @@ describe('team model availability Codex catalog integration', () => {
availabilityStatus: 'available', availabilityStatus: 'available',
availabilityReason: null, availabilityReason: null,
}, },
{
value: 'claude-opus-4-7',
label: 'Opus 4.7',
badgeLabel: 'Opus 4.7',
availabilityStatus: null,
availabilityReason: null,
},
{ {
value: 'claude-opus-4-6', value: 'claude-opus-4-6',
label: 'Opus 4.6', label: 'Opus 4.6',

View file

@ -47,12 +47,17 @@ const TEAM_PROVIDER_LABELS: Record<SupportedProviderId, string> = {
}; };
const ANTHROPIC_ALIAS_LABELS = { const ANTHROPIC_ALIAS_LABELS = {
opus: 'Opus 4.7', opus: 'Opus 4.8',
sonnet: 'Sonnet 4.6', sonnet: 'Sonnet 4.6',
haiku: 'Haiku 4.5', haiku: 'Haiku 4.5',
} as const; } as const;
const ANTHROPIC_VISIBLE_MODEL_FALLBACKS = ['claude-opus-4-7', 'claude-opus-4-7[1m]'] as const; const ANTHROPIC_VISIBLE_MODEL_FALLBACKS = [
'claude-opus-4-8',
'claude-opus-4-8[1m]',
'claude-opus-4-7',
'claude-opus-4-7[1m]',
] as const;
const ANTHROPIC_MODEL_ORDER = [ const ANTHROPIC_MODEL_ORDER = [
'haiku', 'haiku',
@ -60,6 +65,8 @@ const ANTHROPIC_MODEL_ORDER = [
'claude-haiku-4-5', 'claude-haiku-4-5',
'opus', 'opus',
'opus[1m]', 'opus[1m]',
'claude-opus-4-8',
'claude-opus-4-8[1m]',
'claude-opus-4-7', 'claude-opus-4-7',
'claude-opus-4-7[1m]', 'claude-opus-4-7[1m]',
'claude-opus-4-6', 'claude-opus-4-6',
@ -73,6 +80,8 @@ const ANTHROPIC_MODEL_ORDER = [
const TEAM_MODEL_LABEL_OVERRIDES: Record<string, string> = { const TEAM_MODEL_LABEL_OVERRIDES: Record<string, string> = {
default: 'Default', default: 'Default',
...ANTHROPIC_ALIAS_LABELS, ...ANTHROPIC_ALIAS_LABELS,
'claude-opus-4-8': 'Opus 4.8',
'claude-opus-4-8[1m]': 'Opus 4.8 (1M)',
'claude-opus-4-7': 'Opus 4.7', 'claude-opus-4-7': 'Opus 4.7',
'claude-opus-4-7[1m]': 'Opus 4.7 (1M)', 'claude-opus-4-7[1m]': 'Opus 4.7 (1M)',
'claude-sonnet-4-6': 'Sonnet 4.6', 'claude-sonnet-4-6': 'Sonnet 4.6',
@ -99,7 +108,8 @@ const TEAM_PROVIDER_MODEL_OPTIONS: Record<SupportedProviderId, readonly TeamProv
{ {
anthropic: [ anthropic: [
{ value: '', label: 'Default', badgeLabel: 'Default' }, { value: '', label: 'Default', badgeLabel: 'Default' },
{ value: 'opus', label: 'Opus 4.7', badgeLabel: 'Opus 4.7' }, { value: 'opus', label: 'Opus 4.8', badgeLabel: 'Opus 4.8' },
{ value: 'claude-opus-4-7', label: 'Opus 4.7', badgeLabel: 'Opus 4.7' },
{ value: 'claude-opus-4-6', label: 'Opus 4.6', badgeLabel: 'Opus 4.6' }, { value: 'claude-opus-4-6', label: 'Opus 4.6', badgeLabel: 'Opus 4.6' },
{ value: 'sonnet', label: 'Sonnet 4.6', badgeLabel: 'Sonnet 4.6' }, { value: 'sonnet', label: 'Sonnet 4.6', badgeLabel: 'Sonnet 4.6' },
{ value: 'haiku', label: 'Haiku 4.5', badgeLabel: 'Haiku 4.5' }, { value: 'haiku', label: 'Haiku 4.5', badgeLabel: 'Haiku 4.5' },
@ -208,6 +218,8 @@ const SUPPORTED_ANTHROPIC_TEAM_MODELS = new Set<string>([
'sonnet', 'sonnet',
'sonnet[1m]', 'sonnet[1m]',
'haiku', 'haiku',
'claude-opus-4-8',
'claude-opus-4-8[1m]',
'claude-opus-4-7', 'claude-opus-4-7',
'claude-opus-4-7[1m]', 'claude-opus-4-7[1m]',
'claude-opus-4-6', 'claude-opus-4-6',

View file

@ -112,6 +112,7 @@ function isAnthropicNativeLongContextModel(modelName: string | undefined): boole
} }
return ( return (
normalized.startsWith('claude-opus-4-8') ||
normalized.startsWith('claude-opus-4-7') || normalized.startsWith('claude-opus-4-7') ||
normalized.startsWith('claude-opus-4-6') || normalized.startsWith('claude-opus-4-6') ||
normalized.startsWith('claude-sonnet-4-6') || normalized.startsWith('claude-sonnet-4-6') ||

View file

@ -183,7 +183,7 @@ describe('resolveAnthropicRuntimeProfile', () => {
effortResetReason: null, effortResetReason: null,
nextFastMode: 'inherit', nextFastMode: 'inherit',
fastModeResetReason: fastModeResetReason:
'Fast mode is available only for Opus 4.6. Selected model resolves to Opus 4.7 (1M).', 'Fast mode is available only for Opus 4.8. Selected model resolves to Opus 4.7 (1M).',
}); });
}); });

View file

@ -544,7 +544,7 @@ describe('teamModelAvailability', () => {
expect(getTeamModelSelectionError('anthropic', 'opus')).toBeNull(); expect(getTeamModelSelectionError('anthropic', 'opus')).toBeNull();
}); });
it('keeps both Anthropic Opus 4.7 and explicit Opus 4.6 in the fallback selector options', () => { it('keeps Anthropic Opus 4.8, 4.7, and explicit Opus 4.6 in the fallback selector options', () => {
expect(getAvailableTeamProviderModelOptions('anthropic')).toEqual([ expect(getAvailableTeamProviderModelOptions('anthropic')).toEqual([
{ {
value: '', value: '',
@ -555,6 +555,13 @@ describe('teamModelAvailability', () => {
}, },
{ {
value: 'opus', value: 'opus',
label: 'Opus 4.8',
badgeLabel: 'Opus 4.8',
availabilityStatus: 'available',
availabilityReason: null,
},
{
value: 'claude-opus-4-7',
label: 'Opus 4.7', label: 'Opus 4.7',
badgeLabel: 'Opus 4.7', badgeLabel: 'Opus 4.7',
availabilityStatus: 'available', availabilityStatus: 'available',

View file

@ -22,7 +22,7 @@ describe('teamModelCatalog', () => {
).toEqual(['gpt-5.4', 'gpt-5.4-mini', 'gpt-5.3-codex', 'gpt-5.2', 'gpt-5.1-codex-max']); ).toEqual(['gpt-5.4', 'gpt-5.4-mini', 'gpt-5.3-codex', 'gpt-5.2', 'gpt-5.1-codex-max']);
}); });
it('adds curated Anthropic Opus 4.7 badges when the runtime list only reports legacy Opus variants', () => { it('adds curated Anthropic Opus 4.8 badges when the runtime list only reports legacy Opus variants', () => {
expect( expect(
getVisibleTeamProviderModels('anthropic', [ getVisibleTeamProviderModels('anthropic', [
'claude-haiku-4-5-20251001', 'claude-haiku-4-5-20251001',
@ -33,6 +33,8 @@ describe('teamModelCatalog', () => {
]) ])
).toEqual([ ).toEqual([
'claude-haiku-4-5-20251001', 'claude-haiku-4-5-20251001',
'claude-opus-4-8',
'claude-opus-4-8[1m]',
'claude-opus-4-7', 'claude-opus-4-7',
'claude-opus-4-7[1m]', 'claude-opus-4-7[1m]',
'claude-opus-4-6', 'claude-opus-4-6',