From 04f6e4ef881b9d1a32b3b8b27e3bdafd0bf239f2 Mon Sep 17 00:00:00 2001 From: hebulin Date: Mon, 17 Aug 2026 09:14:20 +0800 Subject: [PATCH] fix(model): migrate retired claude-sonnet-4-7 default instead of pinning dead model claude-sonnet-4-7 was retired from the Anthropic API but remains the default model hardcoded in both the webview (DEFAULT_CLAUDE_MODEL_ID, default props) and the Java side (SessionState, HandlerContext, ChatWindowDelegate, ClaudePricingTable). Every flow that falls back to the default - or restores a persisted tab that had Sonnet 4.7 selected - now fails on every send: There is an issue with the selected model (claude-sonnet-4-7[1m]). It may not exist or you may not have access to it. LEGACY_CLAUDE_MODEL_ID_ALIASES also mapped sonnet-4-6 -> sonnet-4-7, i.e. one retired id to another retired id, so normalizeClaudeModelId() kept returning a dead id (#1678). Webview: - DEFAULT_CLAUDE_MODEL_ID: sonnet-4-7 -> sonnet-5 (same-tier successor) - legacy aliases now map every retired id to a live model: sonnet-4-6/sonnet-4-7 -> sonnet-5, opus-4-6 -> opus-4-8 - remove claude-sonnet-4-7 from CLAUDE_MODELS and sonnet47 i18n entries; move the "Use the default model" description to Sonnet 5 (all locales) - default selectedModel props use DEFAULT_CLAUDE_MODEL_ID instead of duplicated literals Java: - sync all four defaults to claude-sonnet-5 - SessionState.setModel() migrates retired ids on write so restored .idea/claudeCodeTabState.xml tabs self-heal instead of spawning a CLI pinned to a dead model; [1m] suffix is preserved - lookup-table entries (pricing/context-limit/effort sets) keep the retired ids so historical usage stats keep resolving Fixes #1678 --- .../handler/core/HandlerContext.java | 2 +- .../provider/pricing/ClaudePricingTable.java | 2 +- .../claudecodegui/session/SessionState.java | 46 +++++++++++- .../claudecodegui/ui/ChatWindowDelegate.java | 2 +- .../session/SessionStateTest.java | 75 +++++++++++++++++++ .../components/ChatInputBox/ButtonArea.tsx | 3 +- .../components/ChatInputBox/ChatInputBox.tsx | 3 +- .../selectors/ModelSelect.test.tsx | 2 +- .../ChatInputBox/selectors/ModelSelect.tsx | 2 - .../src/components/ChatInputBox/types.test.ts | 10 ++- webview/src/components/ChatInputBox/types.ts | 16 ++-- .../useModelStatePersistence.test.ts | 8 +- webview/src/i18n/locales/en.json | 6 +- webview/src/i18n/locales/es.json | 6 +- webview/src/i18n/locales/fr.json | 6 +- webview/src/i18n/locales/hi.json | 6 +- webview/src/i18n/locales/ja.json | 6 +- webview/src/i18n/locales/ko.json | 6 +- webview/src/i18n/locales/pt-BR.json | 6 +- webview/src/i18n/locales/ru.json | 6 +- webview/src/i18n/locales/zh-TW.json | 6 +- webview/src/i18n/locales/zh.json | 6 +- 22 files changed, 156 insertions(+), 75 deletions(-) create mode 100644 src/test/java/com/github/claudecodegui/session/SessionStateTest.java diff --git a/src/main/java/com/github/claudecodegui/handler/core/HandlerContext.java b/src/main/java/com/github/claudecodegui/handler/core/HandlerContext.java index 4eb1a989..ca5182a6 100644 --- a/src/main/java/com/github/claudecodegui/handler/core/HandlerContext.java +++ b/src/main/java/com/github/claudecodegui/handler/core/HandlerContext.java @@ -17,7 +17,7 @@ import java.util.function.Supplier; */ public class HandlerContext { - public static final String DEFAULT_MODEL = "claude-sonnet-4-7"; + public static final String DEFAULT_MODEL = "claude-sonnet-5"; public static final String DEFAULT_PROVIDER = "claude"; private final Project project; diff --git a/src/main/java/com/github/claudecodegui/provider/pricing/ClaudePricingTable.java b/src/main/java/com/github/claudecodegui/provider/pricing/ClaudePricingTable.java index a7695750..9faee7a2 100644 --- a/src/main/java/com/github/claudecodegui/provider/pricing/ClaudePricingTable.java +++ b/src/main/java/com/github/claudecodegui/provider/pricing/ClaudePricingTable.java @@ -13,7 +13,7 @@ import java.util.Map; */ public final class ClaudePricingTable { - public static final String DEFAULT_MODEL = "claude-sonnet-4-7"; + public static final String DEFAULT_MODEL = "claude-sonnet-5"; private static final ClaudePricing DEFAULT_PRICING = new ClaudePricing(3.0, 15.0, 3.75, 0.30); private static final ClaudePricing TIERED_SONNET_PRICING = new ClaudePricing(3.0, 15.0, 3.75, 0.30, 6.0, 22.5, 7.5, 0.60); diff --git a/src/main/java/com/github/claudecodegui/session/SessionState.java b/src/main/java/com/github/claudecodegui/session/SessionState.java index 650ddd30..b327fa33 100644 --- a/src/main/java/com/github/claudecodegui/session/SessionState.java +++ b/src/main/java/com/github/claudecodegui/session/SessionState.java @@ -83,7 +83,7 @@ public class SessionState { // explicit, informed opt-in — see security remediation A: shipping bypass as the // out-of-the-box default removed the only confirmation gate for AI-issued commands. private volatile String permissionMode = "default"; - private volatile String model = "claude-sonnet-4-7"; + private volatile String model = "claude-sonnet-5"; private volatile String provider = "claude"; // Reasoning effort (thinking depth). Null means "do not override SDK/settings". private volatile String reasoningEffort = null; @@ -213,7 +213,49 @@ public class SessionState { } public void setModel(String model) { - this.model = model; + this.model = normalizeRetiredModelId(model); + } + + /** + * Migrate retired Claude model ids to their live replacement on write. + * + *

Persisted tab state (.idea/claudeCodeTabState.xml) and history sessions keep + * whatever model id was saved forever. When a model is retired from the API + * (sonnet-4-6, sonnet-4-7, ...), restoring such a tab would otherwise spawn a CLI + * pinned to a dead model that fails on every send ("It may not exist or you may + * not have access to it") - see #1678. Migrating here self-heals restored tabs + * without touching the persisted XML.

+ * + * @param model raw model id (may be null, blank, carry a [1m] suffix, or be retired) + * @return the model id to store - retired ids mapped to their live replacement, + * anything else (including non-Claude ids) passed through unchanged + */ + static String normalizeRetiredModelId(String model) { + if (model == null) { + return null; + } + String trimmed = model.trim(); + if (trimmed.isEmpty()) { + return model; + } + String base = trimmed; + boolean oneM = false; + if (base.endsWith("[1m]")) { + base = base.substring(0, base.length() - "[1m]".length()); + oneM = true; + } + switch (base) { + case "claude-sonnet-4-6": + case "claude-sonnet-4-7": + base = "claude-sonnet-5"; + break; + case "claude-opus-4-6": + base = "claude-opus-4-8"; + break; + default: + return trimmed; + } + return oneM ? base + "[1m]" : base; } public void setProvider(String provider) { diff --git a/src/main/java/com/github/claudecodegui/ui/ChatWindowDelegate.java b/src/main/java/com/github/claudecodegui/ui/ChatWindowDelegate.java index 6c53c571..23266586 100644 --- a/src/main/java/com/github/claudecodegui/ui/ChatWindowDelegate.java +++ b/src/main/java/com/github/claudecodegui/ui/ChatWindowDelegate.java @@ -440,7 +440,7 @@ public class ChatWindowDelegate { String mode = session != null ? session.getPermissionMode() : "default"; com.github.claudecodegui.notifications.ClaudeNotifier.setMode(project, mode); - String model = session != null ? session.getModel() : "claude-sonnet-4-7"; + String model = session != null ? session.getModel() : "claude-sonnet-5"; com.github.claudecodegui.notifications.ClaudeNotifier.setModel(project, model); try { diff --git a/src/test/java/com/github/claudecodegui/session/SessionStateTest.java b/src/test/java/com/github/claudecodegui/session/SessionStateTest.java new file mode 100644 index 00000000..af3b8dee --- /dev/null +++ b/src/test/java/com/github/claudecodegui/session/SessionStateTest.java @@ -0,0 +1,75 @@ +package com.github.claudecodegui.session; + +import org.junit.Assert; +import org.junit.Test; + +/** + * Regression tests for retired Claude model id migration on session state writes + * (persisted tab / history restore self-heal) - see #1678. + */ +public class SessionStateTest { + + @Test + public void setModelMigratesRetiredSonnet47ToSonnet5() { + SessionState state = new SessionState(); + // Saved by versions <= 0.5.2 where sonnet-4-7 was the default model. + state.setModel("claude-sonnet-4-7"); + Assert.assertEquals("claude-sonnet-5", state.getModel()); + } + + @Test + public void setModelMigratesRetiredSonnet46ToSonnet5() { + SessionState state = new SessionState(); + state.setModel("claude-sonnet-4-6"); + Assert.assertEquals("claude-sonnet-5", state.getModel()); + } + + @Test + public void setModelMigratesRetiredOpus46ToOpus48() { + SessionState state = new SessionState(); + state.setModel("claude-opus-4-6"); + Assert.assertEquals("claude-opus-4-8", state.getModel()); + } + + @Test + public void setModelPreserves1MSuffixWhenMigrating() { + SessionState state = new SessionState(); + state.setModel("claude-sonnet-4-7[1m]"); + Assert.assertEquals("claude-sonnet-5[1m]", state.getModel()); + } + + @Test + public void setModelLeavesLiveModelsUntouched() { + SessionState state = new SessionState(); + state.setModel("claude-sonnet-5"); + Assert.assertEquals("claude-sonnet-5", state.getModel()); + state.setModel("claude-opus-4-8[1m]"); + Assert.assertEquals("claude-opus-4-8[1m]", state.getModel()); + } + + @Test + public void setModelLeavesNonClaudeAndUnknownIdsUntouched() { + SessionState state = new SessionState(); + // Non-Claude provider models must pass through unchanged. + state.setModel("gpt-5.6-sol"); + Assert.assertEquals("gpt-5.6-sol", state.getModel()); + state.setModel("qwen3.5-plus"); + Assert.assertEquals("qwen3.5-plus", state.getModel()); + } + + @Test + public void setModelHandlesNullAndBlank() { + SessionState state = new SessionState(); + state.setModel(null); + Assert.assertNull(state.getModel()); + state.setModel(" "); + Assert.assertEquals(" ", state.getModel()); + } + + @Test + public void defaultModelIsTheLiveSonnet5() { + SessionState state = new SessionState(); + // The initial value must never be a retired id (#1678). + Assert.assertEquals("claude-sonnet-5", state.getModel()); + } +} diff --git a/webview/src/components/ChatInputBox/ButtonArea.tsx b/webview/src/components/ChatInputBox/ButtonArea.tsx index 99c74349..04b26885 100644 --- a/webview/src/components/ChatInputBox/ButtonArea.tsx +++ b/webview/src/components/ChatInputBox/ButtonArea.tsx @@ -1,6 +1,7 @@ import { useCallback, useMemo, useState, useEffect, useRef } from 'react'; import { useTranslation } from 'react-i18next'; import type { ButtonAreaProps, CodexFastMode, ModelInfo, PermissionMode, ReasoningEffort } from './types'; +import { DEFAULT_CLAUDE_MODEL_ID } from './types'; import { CodexFastModeSelect, ConfigSelect, ModelSelect, ModeSelect, ProviderSelect, ReasoningSelect } from './selectors'; import { STORAGE_KEYS, validateCodexCustomModels } from '../../types/provider'; import type { CodexCustomModel } from '../../types/provider'; @@ -73,7 +74,7 @@ export const ButtonArea = ({ hasInputContent = false, isLoading = false, isEnhancing = false, - selectedModel = 'claude-sonnet-4-7', + selectedModel = DEFAULT_CLAUDE_MODEL_ID, permissionMode = 'default', currentProvider = 'claude', reasoningEffort = 'high', diff --git a/webview/src/components/ChatInputBox/ChatInputBox.tsx b/webview/src/components/ChatInputBox/ChatInputBox.tsx index 084f2eb2..53a82e9f 100644 --- a/webview/src/components/ChatInputBox/ChatInputBox.tsx +++ b/webview/src/components/ChatInputBox/ChatInputBox.tsx @@ -14,6 +14,7 @@ import type { ChatInputBoxProps, PermissionMode, } from './types.js'; +import { DEFAULT_CLAUDE_MODEL_ID } from './types.js'; import { ChatInputBoxHeader } from './ChatInputBoxHeader.js'; import { ChatInputBoxFooter } from './ChatInputBoxFooter.js'; import { ResizeHandles } from './ResizeHandles.js'; @@ -76,7 +77,7 @@ export const ChatInputBox = memo(forwardRef { 'claude-opus-5', 'claude-opus-4-8', 'claude-sonnet-5', - 'claude-sonnet-4-7', 'claude-haiku-4-5', ]); const ids = CLAUDE_MODELS.map((model) => model.id); expect(ids).not.toContain('claude-opus-4-7'); expect(ids).not.toContain('claude-opus-4-6'); expect(ids).not.toContain('claude-sonnet-4-6'); + expect(ids).not.toContain('claude-sonnet-4-7'); expect(ids.some((id) => id.endsWith('[1m]'))).toBe(false); }); diff --git a/webview/src/components/ChatInputBox/selectors/ModelSelect.tsx b/webview/src/components/ChatInputBox/selectors/ModelSelect.tsx index e33bb29f..4ade8efa 100644 --- a/webview/src/components/ChatInputBox/selectors/ModelSelect.tsx +++ b/webview/src/components/ChatInputBox/selectors/ModelSelect.tsx @@ -69,7 +69,6 @@ const DEFAULT_MODEL_MAP: Record = AVAILABLE_MODELS.reduce( const MODEL_LABEL_KEYS: Record = { 'claude-opus-5': 'models.claude.opus5.label', 'claude-sonnet-5': 'models.claude.sonnet5.label', - 'claude-sonnet-4-7': 'models.claude.sonnet47.label', 'claude-sonnet-4-6': 'models.claude.sonnet46.label', 'claude-fable-5': 'models.claude.fable5.label', 'claude-opus-4-8': 'models.claude.opus48.label', @@ -89,7 +88,6 @@ const MODEL_LABEL_KEYS: Record = { const MODEL_DESCRIPTION_KEYS: Record = { 'claude-opus-5': 'models.claude.opus5.description', 'claude-sonnet-5': 'models.claude.sonnet5.description', - 'claude-sonnet-4-7': 'models.claude.sonnet47.description', 'claude-sonnet-4-6': 'models.claude.sonnet46.description', 'claude-fable-5': 'models.claude.fable5.description', 'claude-opus-4-8': 'models.claude.opus48.description', diff --git a/webview/src/components/ChatInputBox/types.test.ts b/webview/src/components/ChatInputBox/types.test.ts index 364e0fd5..a5839d94 100644 --- a/webview/src/components/ChatInputBox/types.test.ts +++ b/webview/src/components/ChatInputBox/types.test.ts @@ -20,7 +20,12 @@ describe('normalizeClaudeModelId', () => { it('migrates retired Sonnet 4.6 to the current default', () => { // Saved by versions <= 0.4.7 where sonnet-4-6 was the default model. - expect(normalizeClaudeModelId('claude-sonnet-4-6')).toBe('claude-sonnet-4-7'); + expect(normalizeClaudeModelId('claude-sonnet-4-6')).toBe('claude-sonnet-5'); + }); + + it('migrates retired Sonnet 4.7 to the current default', () => { + // Saved by versions <= 0.5.2 where sonnet-4-7 was the default model (#1678). + expect(normalizeClaudeModelId('claude-sonnet-4-7')).toBe('claude-sonnet-5'); }); it('migrates retired Opus 4.6 to Opus 4.8', () => { @@ -28,7 +33,8 @@ describe('normalizeClaudeModelId', () => { }); it('migrates retired IDs carrying a [1m] suffix', () => { - expect(normalizeClaudeModelId('claude-sonnet-4-6[1m]')).toBe('claude-sonnet-4-7'); + expect(normalizeClaudeModelId('claude-sonnet-4-6[1m]')).toBe('claude-sonnet-5'); + expect(normalizeClaudeModelId('claude-sonnet-4-7[1m]')).toBe('claude-sonnet-5'); expect(normalizeClaudeModelId('claude-opus-4-6[1m]')).toBe('claude-opus-4-8'); }); diff --git a/webview/src/components/ChatInputBox/types.ts b/webview/src/components/ChatInputBox/types.ts index 625f2963..4490902b 100644 --- a/webview/src/components/ChatInputBox/types.ts +++ b/webview/src/components/ChatInputBox/types.ts @@ -301,15 +301,18 @@ export function strip1MContextSuffix(modelId: string | undefined | null): string * CLAUDE_MODELS[0], which is the newest tier and the most likely to be missing * from a user's API relay. */ -export const DEFAULT_CLAUDE_MODEL_ID = 'claude-sonnet-4-7'; +export const DEFAULT_CLAUDE_MODEL_ID = 'claude-sonnet-5'; /** - * Retired model IDs → their current-generation replacement. Lookup happens after + * Retired model IDs -> their current-generation replacement. Lookup happens after * the [1m] suffix is stripped, so keys must be base IDs. Without an entry here a * saved retired model fails validation and silently resets to the fallback. + * Retired ids must always map to a LIVE model - mapping one retired id to another + * (sonnet-4-6 -> sonnet-4-7) kept restoring tabs pinned to a dead model (#1678). */ const LEGACY_CLAUDE_MODEL_ID_ALIASES: Record = { - 'claude-sonnet-4-6': 'claude-sonnet-4-7', + 'claude-sonnet-4-6': 'claude-sonnet-5', + 'claude-sonnet-4-7': 'claude-sonnet-5', 'claude-opus-4-6': 'claude-opus-4-8', }; @@ -345,12 +348,7 @@ export const CLAUDE_MODELS: ModelInfo[] = [ { id: 'claude-sonnet-5', label: 'Sonnet 5', - description: 'Sonnet 5 · Upgraded Sonnet model', - }, - { - id: 'claude-sonnet-4-7', - label: 'Sonnet 4.7', - description: 'Sonnet 4.7 · Use the default model', + description: 'Sonnet 5 · Use the default model', }, { id: 'claude-haiku-4-5', diff --git a/webview/src/hooks/providers/useModelStatePersistence.test.ts b/webview/src/hooks/providers/useModelStatePersistence.test.ts index b3aad1bf..b8f8faa7 100644 --- a/webview/src/hooks/providers/useModelStatePersistence.test.ts +++ b/webview/src/hooks/providers/useModelStatePersistence.test.ts @@ -207,9 +207,9 @@ describe('useModelStatePersistence — retired model migration', () => { renderHook(() => useModelStatePersistence(makeOptions({ setSelectedClaudeModel }))); vi.advanceTimersByTime(200); - expect(setSelectedClaudeModel).toHaveBeenCalledWith('claude-sonnet-4-7'); + expect(setSelectedClaudeModel).toHaveBeenCalledWith('claude-sonnet-5'); expect(setSelectedClaudeModel).not.toHaveBeenCalledWith('claude-fable-5'); - expect(bridgeEventsFor('set_model')).toEqual([['set_model', 'claude-sonnet-4-7']]); + expect(bridgeEventsFor('set_model')).toEqual([['set_model', 'claude-sonnet-5']]); }); it('migrates a backend-supplied retired model via __INITIAL_TAB_MODEL__', () => { @@ -225,8 +225,8 @@ describe('useModelStatePersistence — retired model migration', () => { renderHook(() => useModelStatePersistence(makeOptions({ setSelectedClaudeModel }))); vi.advanceTimersByTime(200); - expect(setSelectedClaudeModel).toHaveBeenCalledWith('claude-sonnet-4-7'); - expect(bridgeEventsFor('set_model')).toEqual([['set_model', 'claude-sonnet-4-7']]); + expect(setSelectedClaudeModel).toHaveBeenCalledWith('claude-sonnet-5'); + expect(bridgeEventsFor('set_model')).toEqual([['set_model', 'claude-sonnet-5']]); }); it('falls back to the default model (not the list head) for unrecognized saved models', () => { diff --git a/webview/src/i18n/locales/en.json b/webview/src/i18n/locales/en.json index 25641556..08062640 100644 --- a/webview/src/i18n/locales/en.json +++ b/webview/src/i18n/locales/en.json @@ -1915,11 +1915,7 @@ }, "sonnet5": { "label": "Sonnet 5", - "description": "Sonnet 5 · Upgraded Sonnet model" - }, - "sonnet47": { - "label": "Sonnet 4.7", - "description": "Sonnet 4.7 · Use the default model" + "description": "Sonnet 5 · Use the default model" }, "opus5": { "label": "Opus 5", diff --git a/webview/src/i18n/locales/es.json b/webview/src/i18n/locales/es.json index 02d6b1d9..e53f4bcb 100644 --- a/webview/src/i18n/locales/es.json +++ b/webview/src/i18n/locales/es.json @@ -1539,11 +1539,7 @@ }, "sonnet5": { "label": "Sonnet 5", - "description": "Sonnet 5 · Modelo mejorado de Sonnet 4.6" - }, - "sonnet47": { - "label": "Sonnet 4.7", - "description": "Sonnet 4.7 · Modelo recomendado por defecto" + "description": "Sonnet 5 · Modelo recomendado por defecto" }, "opus5": { "label": "Opus 5", diff --git a/webview/src/i18n/locales/fr.json b/webview/src/i18n/locales/fr.json index c09907b5..149d0636 100644 --- a/webview/src/i18n/locales/fr.json +++ b/webview/src/i18n/locales/fr.json @@ -1539,11 +1539,7 @@ }, "sonnet5": { "label": "Sonnet 5", - "description": "Sonnet 5 · Modèle amélioré de Sonnet 4.6" - }, - "sonnet47": { - "label": "Sonnet 4.7", - "description": "Sonnet 4.7 · Modèle recommandé par défaut" + "description": "Sonnet 5 · Modèle recommandé par défaut" }, "opus5": { "label": "Opus 5", diff --git a/webview/src/i18n/locales/hi.json b/webview/src/i18n/locales/hi.json index e92bd858..a6144d5c 100644 --- a/webview/src/i18n/locales/hi.json +++ b/webview/src/i18n/locales/hi.json @@ -1538,11 +1538,7 @@ }, "sonnet5": { "label": "Sonnet 5", - "description": "Sonnet 5 · Sonnet 4.6 का अपग्रेड मॉडल" - }, - "sonnet47": { - "label": "Sonnet 4.7", - "description": "Sonnet 4.7 · डिफ़ॉल्ट अनुशंसित मॉडल" + "description": "Sonnet 5 · डिफ़ॉल्ट अनुशंसित मॉडल" }, "opus5": { "label": "Opus 5", diff --git a/webview/src/i18n/locales/ja.json b/webview/src/i18n/locales/ja.json index 75d24055..3153c783 100644 --- a/webview/src/i18n/locales/ja.json +++ b/webview/src/i18n/locales/ja.json @@ -1550,11 +1550,7 @@ }, "sonnet5": { "label": "Sonnet 5", - "description": "Sonnet 5 · Sonnet 4.6 のアップグレードモデル" - }, - "sonnet47": { - "label": "Sonnet 4.7", - "description": "Sonnet 4.7 · デフォルトモデルを使用" + "description": "Sonnet 5 · デフォルトモデルを使用" }, "opus5": { "label": "Opus 5", diff --git a/webview/src/i18n/locales/ko.json b/webview/src/i18n/locales/ko.json index 3cd78903..2724b8df 100644 --- a/webview/src/i18n/locales/ko.json +++ b/webview/src/i18n/locales/ko.json @@ -1634,11 +1634,7 @@ }, "sonnet5": { "label": "Sonnet 5", - "description": "Sonnet 5 · Sonnet 4.6 업그레이드 모델" - }, - "sonnet47": { - "label": "Sonnet 4.7", - "description": "Sonnet 4.7 · 기본 모델 사용" + "description": "Sonnet 5 · 기본 모델 사용" }, "opus5": { "label": "Opus 5", diff --git a/webview/src/i18n/locales/pt-BR.json b/webview/src/i18n/locales/pt-BR.json index 4a3d3aae..f2729d0b 100644 --- a/webview/src/i18n/locales/pt-BR.json +++ b/webview/src/i18n/locales/pt-BR.json @@ -1689,11 +1689,7 @@ }, "sonnet5": { "label": "Sonnet 5", - "description": "Sonnet 5 · Modelo aprimorado do Sonnet 4.6" - }, - "sonnet47": { - "label": "Sonnet 4.7", - "description": "Sonnet 4.7 · Usar o modelo padrão" + "description": "Sonnet 5 · Usar o modelo padrão" }, "opus5": { "label": "Opus 5", diff --git a/webview/src/i18n/locales/ru.json b/webview/src/i18n/locales/ru.json index 9d26b015..33f73794 100644 --- a/webview/src/i18n/locales/ru.json +++ b/webview/src/i18n/locales/ru.json @@ -1565,11 +1565,7 @@ }, "sonnet5": { "label": "Sonnet 5", - "description": "Sonnet 5 · Обновленная модель Sonnet 4.6" - }, - "sonnet47": { - "label": "Sonnet 4.7", - "description": "Sonnet 4.7 · Модель по умолчанию" + "description": "Sonnet 5 · Модель по умолчанию" }, "opus5": { "label": "Opus 5", diff --git a/webview/src/i18n/locales/zh-TW.json b/webview/src/i18n/locales/zh-TW.json index 971c7f67..e6a046b7 100644 --- a/webview/src/i18n/locales/zh-TW.json +++ b/webview/src/i18n/locales/zh-TW.json @@ -1544,11 +1544,7 @@ }, "sonnet5": { "label": "Sonnet 5", - "description": "Sonnet 5 · Sonnet 4.6 升級模型" - }, - "sonnet47": { - "label": "Sonnet 4.7", - "description": "Sonnet 4.7 · 預設推薦模型" + "description": "Sonnet 5 · 預設推薦模型" }, "opus5": { "label": "Opus 5", diff --git a/webview/src/i18n/locales/zh.json b/webview/src/i18n/locales/zh.json index 7292a409..96b76035 100644 --- a/webview/src/i18n/locales/zh.json +++ b/webview/src/i18n/locales/zh.json @@ -1920,11 +1920,7 @@ }, "sonnet5": { "label": "Sonnet 5", - "description": "Sonnet 5 · Sonnet 4.6 升级模型" - }, - "sonnet47": { - "label": "Sonnet 4.7", - "description": "Sonnet 4.7 · 默认推荐模型" + "description": "Sonnet 5 · 默认推荐模型" }, "opus5": { "label": "Opus 5",