From 6eada589aaf2e2955bf4c3ab7285dd2237afa5c9 Mon Sep 17 00:00:00 2001 From: 777genius Date: Fri, 29 May 2026 00:54:33 +0300 Subject: [PATCH] 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. --- .../domain/resolveAnthropicRuntimeProfile.ts | 6 ++++-- .../team/dialogs/OptionalSettingsSection.tsx | 3 ++- .../team/dialogs/TeamModelSelector.tsx | 4 ++-- .../teamModelAvailability.codexCatalog.test.ts | 7 +++++++ src/renderer/utils/teamModelCatalog.ts | 18 +++++++++++++++--- src/shared/utils/contextMetrics.ts | 1 + .../resolveAnthropicRuntimeProfile.test.ts | 2 +- .../utils/teamModelAvailability.test.ts | 9 ++++++++- test/renderer/utils/teamModelCatalog.test.ts | 4 +++- 9 files changed, 43 insertions(+), 11 deletions(-) diff --git a/src/features/anthropic-runtime-profile/core/domain/resolveAnthropicRuntimeProfile.ts b/src/features/anthropic-runtime-profile/core/domain/resolveAnthropicRuntimeProfile.ts index 67027607..23d286a3 100644 --- a/src/features/anthropic-runtime-profile/core/domain/resolveAnthropicRuntimeProfile.ts +++ b/src/features/anthropic-runtime-profile/core/domain/resolveAnthropicRuntimeProfile.ts @@ -95,6 +95,8 @@ function isKnownAnthropicReasoningModel(model: string | null | undefined): boole return ( normalized === 'opus' || normalized === 'sonnet' || + normalized === 'claude-opus-4-8' || + normalized.startsWith('claude-opus-4-8-') || normalized === 'claude-opus-4-7' || normalized.startsWith('claude-opus-4-7-') || normalized === 'claude-opus-4-6' || @@ -221,8 +223,8 @@ export function resolveAnthropicFastMode(params: { 'Fast mode is not supported by this Anthropic runtime.'; } else if (!params.selection.supportsFastMode) { 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.6.'; + ? `Fast mode is available only for Opus 4.8. Selected model resolves to ${params.selection.displayName}.` + : 'Fast mode is available only for Opus 4.8.'; } else if (!params.selection.providerFastModeAvailable) { disabledReason = params.selection.providerFastModeReason ?? 'Fast mode is currently unavailable.'; diff --git a/src/renderer/components/team/dialogs/OptionalSettingsSection.tsx b/src/renderer/components/team/dialogs/OptionalSettingsSection.tsx index 9e75e2a6..72bfb36c 100644 --- a/src/renderer/components/team/dialogs/OptionalSettingsSection.tsx +++ b/src/renderer/components/team/dialogs/OptionalSettingsSection.tsx @@ -18,8 +18,9 @@ interface OptionalSettingsSectionProps { const SUMMARY_PREFIXES_TO_STRIP = ['Provider:', 'Model:', 'Effort:', 'Worktree:']; 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]?6/i, 'Opus 4.6'], [/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]?5/i, 'Sonnet 4.5'], diff --git a/src/renderer/components/team/dialogs/TeamModelSelector.tsx b/src/renderer/components/team/dialogs/TeamModelSelector.tsx index 9533d6f5..6bf26e94 100644 --- a/src/renderer/components/team/dialogs/TeamModelSelector.tsx +++ b/src/renderer/components/team/dialogs/TeamModelSelector.tsx @@ -825,13 +825,13 @@ export const TeamModelSelector: React.FC = ({ 'anthropic', getAnthropicDefaultTeamModel(false), runtimeProviderStatus - ) ?? 'Opus 4.7 (1M)'; + ) ?? 'Opus 4.8 (1M)'; const defaultLimitedContextModel = getRuntimeAwareProviderScopedTeamModelLabel( 'anthropic', getAnthropicDefaultTeamModel(true), runtimeProviderStatus - ) ?? 'Opus 4.7'; + ) ?? 'Opus 4.8'; return t('modelSelector.defaultTooltip.anthropic', { longContextModel: defaultLongContextModel, diff --git a/src/renderer/utils/__tests__/teamModelAvailability.codexCatalog.test.ts b/src/renderer/utils/__tests__/teamModelAvailability.codexCatalog.test.ts index a46a06b5..2d34b82a 100644 --- a/src/renderer/utils/__tests__/teamModelAvailability.codexCatalog.test.ts +++ b/src/renderer/utils/__tests__/teamModelAvailability.codexCatalog.test.ts @@ -431,6 +431,13 @@ describe('team model availability Codex catalog integration', () => { availabilityStatus: 'available', availabilityReason: null, }, + { + value: 'claude-opus-4-7', + label: 'Opus 4.7', + badgeLabel: 'Opus 4.7', + availabilityStatus: null, + availabilityReason: null, + }, { value: 'claude-opus-4-6', label: 'Opus 4.6', diff --git a/src/renderer/utils/teamModelCatalog.ts b/src/renderer/utils/teamModelCatalog.ts index d78cc6e8..300d7d8c 100644 --- a/src/renderer/utils/teamModelCatalog.ts +++ b/src/renderer/utils/teamModelCatalog.ts @@ -47,12 +47,17 @@ const TEAM_PROVIDER_LABELS: Record = { }; const ANTHROPIC_ALIAS_LABELS = { - opus: 'Opus 4.7', + opus: 'Opus 4.8', sonnet: 'Sonnet 4.6', haiku: 'Haiku 4.5', } 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 = [ 'haiku', @@ -60,6 +65,8 @@ const ANTHROPIC_MODEL_ORDER = [ 'claude-haiku-4-5', 'opus', 'opus[1m]', + 'claude-opus-4-8', + 'claude-opus-4-8[1m]', 'claude-opus-4-7', 'claude-opus-4-7[1m]', 'claude-opus-4-6', @@ -73,6 +80,8 @@ const ANTHROPIC_MODEL_ORDER = [ const TEAM_MODEL_LABEL_OVERRIDES: Record = { default: 'Default', ...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[1m]': 'Opus 4.7 (1M)', 'claude-sonnet-4-6': 'Sonnet 4.6', @@ -99,7 +108,8 @@ const TEAM_PROVIDER_MODEL_OPTIONS: Record([ 'sonnet', 'sonnet[1m]', 'haiku', + 'claude-opus-4-8', + 'claude-opus-4-8[1m]', 'claude-opus-4-7', 'claude-opus-4-7[1m]', 'claude-opus-4-6', diff --git a/src/shared/utils/contextMetrics.ts b/src/shared/utils/contextMetrics.ts index f37ff56f..2b676551 100644 --- a/src/shared/utils/contextMetrics.ts +++ b/src/shared/utils/contextMetrics.ts @@ -112,6 +112,7 @@ function isAnthropicNativeLongContextModel(modelName: string | undefined): boole } return ( + normalized.startsWith('claude-opus-4-8') || normalized.startsWith('claude-opus-4-7') || normalized.startsWith('claude-opus-4-6') || normalized.startsWith('claude-sonnet-4-6') || diff --git a/test/features/anthropic-runtime-profile/resolveAnthropicRuntimeProfile.test.ts b/test/features/anthropic-runtime-profile/resolveAnthropicRuntimeProfile.test.ts index 997feb6d..7cbb486b 100644 --- a/test/features/anthropic-runtime-profile/resolveAnthropicRuntimeProfile.test.ts +++ b/test/features/anthropic-runtime-profile/resolveAnthropicRuntimeProfile.test.ts @@ -183,7 +183,7 @@ describe('resolveAnthropicRuntimeProfile', () => { effortResetReason: null, nextFastMode: 'inherit', 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).', }); }); diff --git a/test/renderer/utils/teamModelAvailability.test.ts b/test/renderer/utils/teamModelAvailability.test.ts index 04316b4b..bbb0f861 100644 --- a/test/renderer/utils/teamModelAvailability.test.ts +++ b/test/renderer/utils/teamModelAvailability.test.ts @@ -544,7 +544,7 @@ describe('teamModelAvailability', () => { 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([ { value: '', @@ -555,6 +555,13 @@ describe('teamModelAvailability', () => { }, { value: 'opus', + label: 'Opus 4.8', + badgeLabel: 'Opus 4.8', + availabilityStatus: 'available', + availabilityReason: null, + }, + { + value: 'claude-opus-4-7', label: 'Opus 4.7', badgeLabel: 'Opus 4.7', availabilityStatus: 'available', diff --git a/test/renderer/utils/teamModelCatalog.test.ts b/test/renderer/utils/teamModelCatalog.test.ts index b2476477..75845ba7 100644 --- a/test/renderer/utils/teamModelCatalog.test.ts +++ b/test/renderer/utils/teamModelCatalog.test.ts @@ -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']); }); - 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( getVisibleTeamProviderModels('anthropic', [ 'claude-haiku-4-5-20251001', @@ -33,6 +33,8 @@ describe('teamModelCatalog', () => { ]) ).toEqual([ 'claude-haiku-4-5-20251001', + 'claude-opus-4-8', + 'claude-opus-4-8[1m]', 'claude-opus-4-7', 'claude-opus-4-7[1m]', 'claude-opus-4-6',