chore: update cluade model name

This commit is contained in:
程序员阿江(Relakkes) 2026-04-18 20:34:56 +08:00
parent c444e439b3
commit 20806f406f
45 changed files with 116 additions and 116 deletions

View File

@ -233,8 +233,8 @@ Leader 视图(默认)
| 模型 | 描述 |
|------|------|
| Opus 4.6 | Most capable for ambitious work |
| Opus 4.6 1M | Most capable for ambitious work |
| Opus 4.7 | Most capable for ambitious work |
| Opus 4.7 1M | Most capable for ambitious work |
| Sonnet 4.6 | Most efficient for everyday tasks |
| Haiku 4.5 | Fastest for quick answers |

View File

@ -394,7 +394,7 @@
│ │ Find a small todo in the codebase and do it │ │
│ │ │ │
│ │ ┌─────────────────┐ ┌──────────────┐│ │
│ │ │+ ⚙ Ask perms ▾ │ │Opus 4.6 1M ▾ 🎤││
│ │ │+ ⚙ Ask perms ▾ │ │Opus 4.7 1M ▾ 🎤││
│ │ └─────────────────┘ └──────────────┘│ │
│ └────────────────────────────────────────────────┘ │
└─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─┘
@ -459,10 +459,10 @@
```
┌──────────────────────────────────┐
│ Opus 4.6
│ Opus 4.7
│ Most capable for ambitious work │
│──────────────────────────────────│
│ Opus 4.6 1M ✓ │
│ Opus 4.7 1M ✓ │
│ Most capable for ambitious work │
│──────────────────────────────────│
│ Sonnet 4.6 │
@ -694,7 +694,7 @@
│ │ 24 hours. Summarize what changed, │ │
│ │ call out any risky patterns... │ │
│ │ │ │
│ │ ⚙ Ask permissions ▾ Opus 4.6 1M ▾ │ │
│ │ ⚙ Ask permissions ▾ Opus 4.7 1M ▾ │ │
│ │ [📁 Select folder] □worktree │ │
│ └──────────────────────────────────────┘ │
│ │
@ -875,7 +875,7 @@
### 8.4 模型切换流程
```
用户点击模型名称 (Opus 4.6 1M)
用户点击模型名称 (Opus 4.7 1M)
→ 展开下拉菜单(模型列表 + Effort 等级)
→ 用户选择新模型
→ 或调整 Effort 等级

View File

@ -258,7 +258,7 @@
<button class="w-full text-left p-2.5 rounded-lg hover:bg-surface-container-high transition-colors flex items-center justify-between">
<div class="flex items-center gap-2">
<span class="material-symbols-outlined text-sm text-outline">psychology</span>
<span class="text-sm">Opus 4.6</span>
<span class="text-sm">Opus 4.7</span>
</div>
</button>
<button class="w-full text-left p-2.5 rounded-lg bg-primary/5 text-primary flex items-center justify-between">

View File

@ -171,7 +171,7 @@ function ApplyEffortAndClose(t0) {
export async function call(onDone: LocalJSXCommandOnDone, _context: unknown, args?: string): Promise<React.ReactNode> {
args = args?.trim() || '';
if (COMMON_HELP_ARGS.includes(args)) {
onDone('Usage: /effort [low|medium|high|max|auto]\n\nEffort levels:\n- low: Quick, straightforward implementation\n- medium: Balanced approach with standard testing\n- high: Comprehensive implementation with extensive testing\n- max: Maximum capability with deepest reasoning (Opus 4.6 only)\n- auto: Use the default effort level for your model');
onDone('Usage: /effort [low|medium|high|max|auto]\n\nEffort levels:\n- low: Quick, straightforward implementation\n- medium: Balanced approach with standard testing\n- high: Comprehensive implementation with extensive testing\n- max: Maximum capability with deepest reasoning (Opus 4.7 only)\n- auto: Use the default effort level for your model');
return;
}
if (!args || args === 'current' || args === 'status') {

View File

@ -150,7 +150,7 @@ function SetModelAndClose({
// @[MODEL LAUNCH]: Update check for 1M access.
if (model && isOpus1mUnavailable(model)) {
onDone(`Opus 4.6 with 1M context is not available for your account. Learn more: https://code.claude.com/docs/en/model-config#extended-context-with-1m`, {
onDone(`Opus 4.7 with 1M context is not available for your account. Learn more: https://code.claude.com/docs/en/model-config#extended-context-with-1m`, {
display: 'system'
});
return;

View File

@ -217,7 +217,7 @@ function EffortOptionLabel(t0) {
* - Everyone else: mark as dismissed so it never shows
*/
export function shouldShowEffortCallout(model: string): boolean {
// Only show for Opus 4.6 for now
// Only show for Opus 4.7 for now
const parsed = parseUserSpecifiedModel(model);
if (!parsed.toLowerCase().includes('opus-4-6')) {
return false;

View File

@ -10,7 +10,7 @@ export const LIGHTNING_BOLT = '↯' // \u21af - used for fast mode indicator
export const EFFORT_LOW = '○' // \u25cb - effort level: low
export const EFFORT_MEDIUM = '◐' // \u25d0 - effort level: medium
export const EFFORT_HIGH = '●' // \u25cf - effort level: high
export const EFFORT_MAX = '◉' // \u25c9 - effort level: max (Opus 4.6 only)
export const EFFORT_MAX = '◉' // \u25c9 - effort level: max (Opus 4.7 only)
// Media/trigger status indicators
export const PLAY_ICON = '\u25b6' // ▶

View File

@ -115,11 +115,11 @@ export const SYSTEM_PROMPT_DYNAMIC_BOUNDARY =
'__SYSTEM_PROMPT_DYNAMIC_BOUNDARY__'
// @[MODEL LAUNCH]: Update the latest frontier model.
const FRONTIER_MODEL_NAME = 'Claude Opus 4.6'
const FRONTIER_MODEL_NAME = 'Claude Opus 4.7'
// @[MODEL LAUNCH]: Update the model family IDs below to the latest in each tier.
const CLAUDE_4_5_OR_4_6_MODEL_IDS = {
opus: 'claude-opus-4-6',
opus: 'claude-opus-4-7',
sonnet: 'claude-sonnet-4-6',
haiku: 'claude-haiku-4-5',
}
@ -693,7 +693,7 @@ export async function computeSimpleEnvInfo(
knowledgeCutoffMessage,
process.env.USER_TYPE === 'ant' && isUndercover()
? null
: `The most recent Claude model family is Claude 4.5/4.6. Model IDs — Opus 4.6: '${CLAUDE_4_5_OR_4_6_MODEL_IDS.opus}', Sonnet 4.6: '${CLAUDE_4_5_OR_4_6_MODEL_IDS.sonnet}', Haiku 4.5: '${CLAUDE_4_5_OR_4_6_MODEL_IDS.haiku}'. When building AI applications, default to the latest and most capable Claude models.`,
: `The most recent Claude model family is Claude 4.5/4.6. Model IDs — Opus 4.7: '${CLAUDE_4_5_OR_4_6_MODEL_IDS.opus}', Sonnet 4.6: '${CLAUDE_4_5_OR_4_6_MODEL_IDS.sonnet}', Haiku 4.5: '${CLAUDE_4_5_OR_4_6_MODEL_IDS.haiku}'. When building AI applications, default to the latest and most capable Claude models.`,
process.env.USER_TYPE === 'ant' && isUndercover()
? null
: `Claude Code is available as a CLI in the terminal, desktop app (Mac/Windows), web app (claude.ai/code), and IDE extensions (VS Code, JetBrains).`,
@ -714,7 +714,7 @@ function getKnowledgeCutoff(modelId: string): string | null {
const canonical = getCanonicalName(modelId)
if (canonical.includes('claude-sonnet-4-6')) {
return 'August 2025'
} else if (canonical.includes('claude-opus-4-6')) {
} else if (canonical.includes('claude-opus-4-7')) {
return 'May 2025'
} else if (canonical.includes('claude-opus-4-5')) {
return 'May 2025'

View File

@ -71,7 +71,7 @@ export const ThinkingAdaptiveSchema = lazySchema(() =>
.object({
type: z.literal('adaptive'),
})
.describe('Claude decides when and how much to think (Opus 4.6+).'),
.describe('Claude decides when and how much to think (Opus 4.7+).'),
)
export const ThinkingEnabledSchema = lazySchema(() =>

View File

@ -26,7 +26,7 @@ c => {
if (!recent(ts)) return;
return {
key: 'opus-pro-update',
text: isLegacyRemap ? 'Model updated to Opus 4.6 · Set CLAUDE_CODE_DISABLE_LEGACY_MODEL_REMAP=1 to opt out' : 'Model updated to Opus 4.6',
text: isLegacyRemap ? 'Model updated to Opus 4.7 · Set CLAUDE_CODE_DISABLE_LEGACY_MODEL_REMAP=1 to opt out' : 'Model updated to Opus 4.7',
color: 'suggestion',
priority: 'high',
timeoutMs: isLegacyRemap ? 8000 : 3000

View File

@ -4,7 +4,7 @@ import {
} from '../utils/settings/settings.js'
/**
* Migrate users on removed fennec model aliases to their new Opus 4.6 aliases.
* Migrate users on removed fennec model aliases to their new Opus 4.7 aliases.
* - fennec-latest opus
* - fennec-latest[1m] opus[1m]
* - fennec-fast-latest opus[1m] + fast mode

View File

@ -13,7 +13,7 @@ import {
/**
* Migrate first-party users off explicit Opus 4.0/4.1 model strings.
*
* The 'opus' alias already resolves to Opus 4.6 for 1P, so anyone still
* The 'opus' alias already resolves to Opus 4.7 for 1P, so anyone still
* on an explicit 4.0/4.1 string pinned it in settings before 4.5 launched.
* parseUserSpecifiedModel now silently remaps these at runtime anyway
* this migration cleans up the settings file so /model shows the right

View File

@ -151,7 +151,7 @@ export function Doctor(t0) {
upperLimit: TASK_MAX_OUTPUT_UPPER_LIMIT
}, {
name: "CLAUDE_CODE_MAX_OUTPUT_TOKENS",
...getModelMaxOutputTokens("claude-opus-4-6")
...getModelMaxOutputTokens("claude-opus-4-7")
}];
t4 = envVars.map(_temp8).filter(_temp9);
$[5] = t4;

View File

@ -2045,7 +2045,7 @@ export function REPL({
// Undercover auto-enable explainer (ant-only, eliminated from external builds)
if ("external" === 'ant' && allowDialogsWithAnimation && showUndercoverCallout) return 'undercover-callout';
// Effort callout (shown once for Opus 4.6 users when effort is enabled)
// Effort callout (shown once for Opus 4.7 users when effort is enabled)
if (allowDialogsWithAnimation && showEffortCallout) return 'effort-callout';
// Remote callout (shown once before first bridge enable)

View File

@ -223,7 +223,7 @@ describe('Business Flow: Agent Management', () => {
const { status, data } = await api('POST', '/api/agents', {
name: 'security-auditor',
description: 'Audits code for security vulnerabilities',
model: 'claude-opus-4-6',
model: 'claude-opus-4-7',
tools: ['Read', 'Grep', 'Glob', 'Bash'],
systemPrompt: 'You are a security expert. Focus on OWASP top 10.',
color: 'red',
@ -258,7 +258,7 @@ describe('Business Flow: Agent Management', () => {
const { data } = await api('GET', '/api/agents/security-auditor')
expect(data.agent.name).toBe('security-auditor')
expect(data.agent.description).toContain('security')
expect(data.agent.model).toBe('claude-opus-4-6')
expect(data.agent.model).toBe('claude-opus-4-7')
expect(data.agent.systemPrompt).toContain('OWASP')
})
@ -323,8 +323,8 @@ describe('Business Flow: Models & Effort', () => {
const { data } = await api('GET', '/api/models')
expect(data.models.length).toBe(4)
const names = data.models.map((m: any) => m.name)
expect(names).toContain('Opus 4.6')
expect(names).toContain('Opus 4.6 1M')
expect(names).toContain('Opus 4.7')
expect(names).toContain('Opus 4.7 1M')
expect(names).toContain('Sonnet 4.6')
expect(names).toContain('Haiku 4.5')
})
@ -334,15 +334,15 @@ describe('Business Flow: Models & Effort', () => {
expect(data.model.id).toBe('claude-sonnet-4-6')
})
it('should switch to Opus 4.6', async () => {
it('should switch to Opus 4.7', async () => {
const { status } = await api('PUT', '/api/models/current', {
modelId: 'claude-opus-4-6',
modelId: 'claude-opus-4-7',
})
expect(status).toBe(200)
const { data } = await api('GET', '/api/models/current')
expect(data.model.id).toBe('claude-opus-4-6')
expect(data.model.name).toBe('Opus 4.6')
expect(data.model.id).toBe('claude-opus-4-7')
expect(data.model.name).toBe('Opus 4.7')
})
it('should switch to Haiku 4.5', async () => {
@ -389,13 +389,13 @@ describe('Business Flow: Models & Effort', () => {
})
it('should persist model and effort to settings file', async () => {
await api('PUT', '/api/models/current', { modelId: 'claude-opus-4-6' })
await api('PUT', '/api/models/current', { modelId: 'claude-opus-4-7' })
await api('PUT', '/api/effort', { level: 'high' })
const settingsPath = path.join(tmpDir, 'settings.json')
const raw = await fs.readFile(settingsPath, 'utf-8')
const settings = JSON.parse(raw)
expect(settings.model).toBe('claude-opus-4-6')
expect(settings.model).toBe('claude-opus-4-7')
expect(settings.effort).toBe('high')
})
})
@ -716,7 +716,7 @@ describe('Business Flow: Settings Persistence', () => {
it('should write and read complex settings', async () => {
const settings = {
theme: 'dark',
model: 'claude-opus-4-6',
model: 'claude-opus-4-7',
effort: 'high',
outputStyle: 'verbose',
permissions: {
@ -729,7 +729,7 @@ describe('Business Flow: Settings Persistence', () => {
const { data } = await api('GET', '/api/settings/user')
expect(data.theme).toBe('dark')
expect(data.model).toBe('claude-opus-4-6')
expect(data.model).toBe('claude-opus-4-7')
expect(data.permissions.allow).toContain('Read')
expect(data.permissions.deny).toContain('Bash(rm -rf /)')
})

View File

@ -159,7 +159,7 @@ describe('E2E: Full Flow', () => {
it('should list available models', async () => {
const { data } = await api('GET', '/api/models')
expect(data.models.length).toBe(4)
expect(data.models[0].name).toBe('Opus 4.6')
expect(data.models[0].name).toBe('Opus 4.7')
})
it('should switch model', async () => {

View File

@ -90,10 +90,10 @@ describe('Real Provider Configs', () => {
baseUrl: 'https://api.jiekou.ai/anthropic',
apiKey: 'sk-fake-test-key-for-testing-only',
models: {
main: 'claude-opus-4-6',
main: 'claude-opus-4-7',
haiku: 'claude-haiku-4-5',
sonnet: 'claude-sonnet-4-6',
opus: 'claude-opus-4-6',
opus: 'claude-opus-4-7',
},
})
@ -107,7 +107,7 @@ describe('Real Provider Configs', () => {
settings = await readCcHahaSettings()
expect((settings.env as Record<string, string>).ANTHROPIC_BASE_URL).toBe('https://api.jiekou.ai/anthropic')
expect((settings.env as Record<string, string>).ANTHROPIC_AUTH_TOKEN).toBe('sk-fake-test-key-for-testing-only')
expect((settings.env as Record<string, string>).ANTHROPIC_MODEL).toBe('claude-opus-4-6')
expect((settings.env as Record<string, string>).ANTHROPIC_MODEL).toBe('claude-opus-4-7')
// 验证 activeId 正确
const list = await service.listProviders()
@ -139,10 +139,10 @@ describe('Real Provider Configs', () => {
baseUrl: 'https://api.jiekou.ai/anthropic',
apiKey: 'sk_test',
models: {
main: 'claude-opus-4-6',
main: 'claude-opus-4-7',
haiku: 'claude-haiku-4-5',
sonnet: 'claude-sonnet-4-6',
opus: 'claude-opus-4-6',
opus: 'claude-opus-4-7',
},
})
await service.activateProvider(provider.id)

View File

@ -79,7 +79,7 @@ function makeAssistantEntry(content: string, parentUuid?: string): Record<string
isSidechain: false,
type: 'assistant',
message: {
model: 'claude-opus-4-6',
model: 'claude-opus-4-7',
id: `msg_${crypto.randomUUID().slice(0, 20)}`,
type: 'message',
role: 'assistant',
@ -261,7 +261,7 @@ describe('SessionService', () => {
isSidechain: false,
type: 'assistant',
message: {
model: 'claude-opus-4-6',
model: 'claude-opus-4-7',
id: `msg_${crypto.randomUUID().slice(0, 20)}`,
type: 'message',
role: 'assistant',
@ -282,7 +282,7 @@ describe('SessionService', () => {
isSidechain: true,
type: 'assistant',
message: {
model: 'claude-opus-4-6',
model: 'claude-opus-4-7',
id: `msg_${crypto.randomUUID().slice(0, 20)}`,
type: 'message',
role: 'assistant',

View File

@ -64,11 +64,11 @@ describe('SettingsService', () => {
it('should write and read user settings', async () => {
const svc = new SettingsService()
await svc.updateUserSettings({ theme: 'dark', model: 'claude-opus-4-6' })
await svc.updateUserSettings({ theme: 'dark', model: 'claude-opus-4-7' })
const settings = await svc.getUserSettings()
expect(settings.theme).toBe('dark')
expect(settings.model).toBe('claude-opus-4-6')
expect(settings.model).toBe('claude-opus-4-7')
})
it('should merge settings on update (shallow merge)', async () => {
@ -97,14 +97,14 @@ describe('SettingsService', () => {
await fs.mkdir(path.join(projectRoot, '.claude'), { recursive: true })
const svc = new SettingsService(projectRoot)
await svc.updateUserSettings({ theme: 'dark', model: 'claude-opus-4-6' })
await svc.updateUserSettings({ theme: 'dark', model: 'claude-opus-4-7' })
await svc.updateProjectSettings({ theme: 'light' })
const merged = await svc.getSettings()
// project overrides user
expect(merged.theme).toBe('light')
// user value preserved when not overridden
expect(merged.model).toBe('claude-opus-4-6')
expect(merged.model).toBe('claude-opus-4-7')
})
it('should get default permission mode', async () => {
@ -168,7 +168,7 @@ describe('Settings API', () => {
it('PUT /api/settings/user should update user settings', async () => {
const { req, url, segments } = makeRequest('PUT', '/api/settings/user', {
model: 'claude-opus-4-6',
model: 'claude-opus-4-7',
})
const res = await handleSettingsApi(req, url, segments)
@ -180,7 +180,7 @@ describe('Settings API', () => {
const { req: r2, url: u2, segments: s2 } = makeRequest('GET', '/api/settings/user')
const res2 = await handleSettingsApi(r2, u2, s2)
const body2 = await res2.json()
expect(body2.model).toBe('claude-opus-4-6')
expect(body2.model).toBe('claude-opus-4-7')
})
it('GET /api/permissions/mode should return default mode', async () => {
@ -250,20 +250,20 @@ describe('Models API', () => {
it('PUT /api/models/current should switch model', async () => {
const { req, url, segments } = makeRequest('PUT', '/api/models/current', {
modelId: 'claude-opus-4-6',
modelId: 'claude-opus-4-7',
})
const res = await handleModelsApi(req, url, segments)
expect(res.status).toBe(200)
const body = await res.json()
expect(body.ok).toBe(true)
expect(body.model).toBe('claude-opus-4-6')
expect(body.model).toBe('claude-opus-4-7')
// Verify persisted
const { req: r2, url: u2, segments: s2 } = makeRequest('GET', '/api/models/current')
const res2 = await handleModelsApi(r2, u2, s2)
const body2 = await res2.json()
expect(body2.model.id).toBe('claude-opus-4-6')
expect(body2.model.id).toBe('claude-opus-4-7')
})
it('PUT /api/models/current should reject missing modelId', async () => {

View File

@ -56,7 +56,7 @@ function makeTeamConfig(overrides?: Record<string, unknown>) {
agentId: 'agent-lead',
name: 'Lead Agent',
agentType: 'lead',
model: 'claude-opus-4-6',
model: 'claude-opus-4-7',
color: '#ff0000',
joinedAt: 1700000000000,
tmuxPaneId: '%0',

View File

@ -85,7 +85,7 @@ function makeTeamConfig(overrides?: Record<string, unknown>) {
agentId: 'agent-lead',
name: 'Lead Agent',
agentType: 'lead',
model: 'claude-opus-4-6',
model: 'claude-opus-4-7',
color: '#ff0000',
joinedAt: 1700000000000,
tmuxPaneId: '%0',

View File

@ -16,8 +16,8 @@ import { ApiError, errorResponse } from '../middleware/errorHandler.js'
const DEFAULT_MODELS = [
{
id: 'claude-opus-4-6',
name: 'Opus 4.6',
id: 'claude-opus-4-7',
name: 'Opus 4.7',
description: 'Most capable for ambitious work',
context: '1m',
},
@ -37,7 +37,7 @@ const DEFAULT_MODELS = [
const EFFORT_LEVELS = ['low', 'medium', 'high', 'max'] as const
const DEFAULT_MODEL = 'claude-opus-4-6'
const DEFAULT_MODEL = 'claude-opus-4-7'
const DEFAULT_EFFORT = 'max'
const settingsService = new SettingsService()
@ -162,7 +162,7 @@ async function handleCurrentModel(req: Request): Promise<Response> {
throw ApiError.badRequest('Missing or invalid "modelId" in request body')
}
// Parse composite IDs like 'claude-opus-4-6-20250610:1m'
// Parse composite IDs like 'claude-opus-4-7-20250610:1m'
// Persist the base model ID for CLI compatibility and context tier separately
const colonIdx = modelId.indexOf(':')
const baseId = colonIdx !== -1 ? modelId.slice(0, colonIdx) : modelId

View File

@ -943,7 +943,7 @@ function get3PModelFallbackSuggestion(model: string): string | undefined {
}
// @[MODEL LAUNCH]: Add a fallback suggestion chain for the new model → previous version for 3P
const m = model.toLowerCase()
// If the failing model looks like an Opus 4.6 variant, suggest the default Opus (4.1 for 3P)
// If the failing model looks like an Opus 4.7 variant, suggest the default Opus (4.1 for 3P)
if (m.includes('opus-4-6') || m.includes('opus_4_6')) {
return getModelStrings().opus41
}

View File

@ -34,8 +34,8 @@ import typescriptClaudeApiToolUse from './claude-api/typescript/claude-api/tool-
// - claude-api/SKILL.md (Current Models pricing table)
// - claude-api/shared/models.md (full model catalog with legacy versions and alias mappings)
export const SKILL_MODEL_VARS = {
OPUS_ID: 'claude-opus-4-6',
OPUS_NAME: 'Claude Opus 4.6',
OPUS_ID: 'claude-opus-4-7',
OPUS_NAME: 'Claude Opus 4.7',
SONNET_ID: 'claude-sonnet-4-6',
SONNET_NAME: 'Claude Sonnet 4.6',
HAIKU_ID: 'claude-haiku-4-5',

View File

@ -730,7 +730,7 @@ export const CYBER_RISK_MITIGATION_REMINDER =
'\n\n<system-reminder>\nWhenever you read a file, you should consider whether it would be considered malware. You CAN and SHOULD provide analysis of malware, what it is doing. But you MUST refuse to improve or augment the code. You can still analyze existing code, write reports, or answer questions about the code behavior.\n</system-reminder>\n'
// Models where cyber risk mitigation should be skipped
const MITIGATION_EXEMPT_MODELS = new Set(['claude-opus-4-6'])
const MITIGATION_EXEMPT_MODELS = new Set(['claude-opus-4-7'])
function shouldIncludeFileReadMitigation(): boolean {
const shortName = getCanonicalName(getMainLoopModel())

View File

@ -61,7 +61,7 @@ describe('CronTaskMeta type coverage', () => {
name: 'test-name',
description: 'test description',
folder: '/test/folder',
model: 'claude-opus-4-6',
model: 'claude-opus-4-7',
permissionMode: 'ask',
worktree: false,
frequency: 'daily',

View File

@ -69,13 +69,13 @@ export function getAttributionTexts(): AttributionTexts {
// @[MODEL LAUNCH]: Update the hardcoded fallback model name below (guards against codename leaks).
// For internal repos, use the real model name. For external repos,
// fall back to "Claude Opus 4.6" for unrecognized models to avoid leaking codenames.
// fall back to "Claude Opus 4.7" for unrecognized models to avoid leaking codenames.
const model = getMainLoopModel()
const isKnownPublicModel = getPublicModelDisplayName(model) !== null
const modelName =
isInternalModelRepoCached() || isKnownPublicModel
? getPublicModelName(model)
: 'Claude Opus 4.6'
: 'Claude Opus 4.7'
const defaultAttribution = `🤖 Generated with [Claude Code](${PRODUCT_URL})`
const defaultCommit = `Co-Authored-By: ${modelName} <noreply@anthropic.com>`

View File

@ -151,7 +151,7 @@ export function modelSupportsStructuredOutputs(model: string): boolean {
canonical.includes('claude-sonnet-4-5') ||
canonical.includes('claude-opus-4-1') ||
canonical.includes('claude-opus-4-5') ||
canonical.includes('claude-opus-4-6') ||
canonical.includes('claude-opus-4-7') ||
canonical.includes('claude-haiku-4-5')
)
}

View File

@ -153,7 +153,7 @@ export function sanitizeSurfaceKey(surfaceKey: string): string {
*/
export function sanitizeModelName(shortName: string): string {
// Map internal variants to public equivalents based on model family
if (shortName.includes('opus-4-6')) return 'claude-opus-4-6'
if (shortName.includes('opus-4-6')) return 'claude-opus-4-7'
if (shortName.includes('opus-4-5')) return 'claude-opus-4-5'
if (shortName.includes('opus-4-1')) return 'claude-opus-4-1'
if (shortName.includes('opus-4')) return 'claude-opus-4'

View File

@ -401,7 +401,7 @@ export type GlobalConfig = {
modelSwitchCalloutLastShown?: number // Timestamp of last shown (don't show for 24h)
modelSwitchCalloutVersion?: string
// Effort callout tracking - shown once for Opus 4.6 users
// Effort callout tracking - shown once for Opus 4.7 users
effortCalloutDismissed?: boolean // v1 - legacy, read to suppress v2 for Pro users who already saw it
effortCalloutV2Dismissed?: boolean

View File

@ -74,7 +74,7 @@ export type CronTask = {
description?: string
/** Working directory for the task execution. */
folder?: string
/** Model to use (e.g. "claude-opus-4-6", "claude-sonnet-4-6"). */
/** Model to use (e.g. "claude-opus-4-7", "claude-sonnet-4-6"). */
model?: string
/** Permission mode: "ask" | "auto-accept" | "plan" | "bypass". */
permissionMode?: string

View File

@ -49,7 +49,7 @@ export function modelSupportsEffort(model: string): boolean {
}
// @[MODEL LAUNCH]: Add the new model to the allowlist if it supports 'max' effort.
// Per API docs, 'max' is Opus 4.6 only for public models — other models return an error.
// Per API docs, 'max' is Opus 4.7 only for public models — other models return an error.
export function modelSupportsMaxEffort(model: string): boolean {
const supported3P = get3PModelCapabilityOverride(model, 'max_effort')
if (supported3P !== undefined) {
@ -230,7 +230,7 @@ export function getEffortLevelDescription(level: EffortLevel): string {
case 'high':
return 'Comprehensive implementation with extensive testing and documentation'
case 'max':
return 'Maximum capability with deepest reasoning (Opus 4.6 only)'
return 'Maximum capability with deepest reasoning (Opus 4.7 only)'
}
}
@ -304,7 +304,7 @@ export function getDefaultEffortForModel(
// the model launch DRI and research. Default effort is a sensitive setting
// that can greatly affect model quality and bashing.
// Default effort on Opus 4.6 to medium for Pro.
// Default effort on Opus 4.7 to medium for Pro.
// Max/Team also get medium when the tengu_grey_step2 config is enabled.
if (model.toLowerCase().includes('opus-4-6')) {
if (isProSubscriber()) {

View File

@ -140,7 +140,7 @@ export function getFastModeUnavailableReason(): string | null {
}
// @[MODEL LAUNCH]: Update supported Fast Mode models.
export const FAST_MODE_MODEL_DISPLAY = 'Opus 4.6'
export const FAST_MODE_MODEL_DISPLAY = 'Opus 4.7'
export function getFastModeModel(): string {
return 'opus' + (isOpus1mMergeEnabled() ? '[1m]' : '')

View File

@ -99,8 +99,8 @@ export function getAgentModel(
* tier. When it does, the subagent inherits the parent's exact model string
* instead of resolving the alias to a provider default.
*
* Prevents surprising downgrades: a Vertex user on Opus 4.6 (via /model) who
* spawns a subagent with `model: opus` should get Opus 4.6, not whatever
* Prevents surprising downgrades: a Vertex user on Opus 4.7 (via /model) who
* spawns a subagent with `model: opus` should get Opus 4.7, not whatever
* getDefaultOpusModel() returns for 3P.
* See https://github.com/anthropics/claude-code/issues/30815.
*

View File

@ -215,7 +215,7 @@ export type BedrockRegionPrefix = (typeof BEDROCK_REGION_PREFIXES)[number]
* For example:
* - "eu.anthropic.claude-sonnet-4-5-20250929-v1:0" "eu"
* - "us.anthropic.claude-3-7-sonnet-20250219-v1:0" "us"
* - "arn:aws:bedrock:ap-northeast-2:123:inference-profile/global.anthropic.claude-opus-4-6-v1" "global"
* - "arn:aws:bedrock:ap-northeast-2:123:inference-profile/global.anthropic.claude-opus-4-7-v1" "global"
* - "anthropic.claude-3-5-sonnet-20241022-v2:0" undefined (foundation model)
* - "claude-sonnet-4-5-20250929" undefined (first-party format)
*/

View File

@ -70,10 +70,10 @@ export const CLAUDE_OPUS_4_5_CONFIG = {
} as const satisfies ModelConfig
export const CLAUDE_OPUS_4_6_CONFIG = {
firstParty: 'claude-opus-4-6',
bedrock: 'us.anthropic.claude-opus-4-6-v1',
vertex: 'claude-opus-4-6',
foundry: 'claude-opus-4-6',
firstParty: 'claude-opus-4-7',
bedrock: 'us.anthropic.claude-opus-4-7-v1',
vertex: 'claude-opus-4-7',
foundry: 'claude-opus-4-7',
} as const satisfies ModelConfig
export const CLAUDE_SONNET_4_6_CONFIG = {
@ -100,7 +100,7 @@ export const ALL_MODEL_CONFIGS = {
export type ModelKey = keyof typeof ALL_MODEL_CONFIGS
/** Union of all canonical first-party model IDs, e.g. 'claude-opus-4-6' | 'claude-sonnet-4-5-20250929' | … */
/** Union of all canonical first-party model IDs, e.g. 'claude-opus-4-7' | 'claude-sonnet-4-5-20250929' | … */
export type CanonicalModelId =
(typeof ALL_MODEL_CONFIGS)[ModelKey]['firstParty']

View File

@ -211,15 +211,15 @@ export function getDefaultMainLoopModel(): ModelName {
/**
* Pure string-match that strips date/provider suffixes from a first-party model
* name. Input must already be a 1P-format ID (e.g. 'claude-3-7-sonnet-20250219',
* 'us.anthropic.claude-opus-4-6-v1:0'). Does not touch settings, so safe at
* 'us.anthropic.claude-opus-4-7-v1:0'). Does not touch settings, so safe at
* module top-level (see MODEL_COSTS in modelCost.ts).
*/
export function firstPartyNameToCanonical(name: ModelName): ModelShortName {
name = name.toLowerCase()
// Special cases for Claude 4+ models to differentiate versions
// Order matters: check more specific versions first (4-5 before 4)
if (name.includes('claude-opus-4-6')) {
return 'claude-opus-4-6'
if (name.includes('claude-opus-4-7')) {
return 'claude-opus-4-7'
}
if (name.includes('claude-opus-4-5')) {
return 'claude-opus-4-5'
@ -288,9 +288,9 @@ export function getClaudeAiUserDefaultModelDescription(
): string {
if (isMaxSubscriber() || isTeamPremiumSubscriber()) {
if (isOpus1mMergeEnabled()) {
return `Opus 4.6 with 1M context · Most capable for complex work${fastMode ? getOpus46PricingSuffix(true) : ''}`
return `Opus 4.7 with 1M context · Most capable for complex work${fastMode ? getOpus46PricingSuffix(true) : ''}`
}
return `Opus 4.6 · Most capable for complex work${fastMode ? getOpus46PricingSuffix(true) : ''}`
return `Opus 4.7 · Most capable for complex work${fastMode ? getOpus46PricingSuffix(true) : ''}`
}
return 'Sonnet 4.6 · Best for everyday tasks'
}
@ -299,7 +299,7 @@ export function renderDefaultModelSetting(
setting: ModelName | ModelAlias,
): string {
if (setting === 'opusplan') {
return 'Opus 4.6 in plan mode, else Sonnet 4.6'
return 'Opus 4.7 in plan mode, else Sonnet 4.6'
}
return renderModelName(parseUserSpecifiedModel(setting))
}
@ -349,9 +349,9 @@ export function renderModelSetting(setting: ModelName | ModelAlias): string {
export function getPublicModelDisplayName(model: ModelName): string | null {
switch (model) {
case getModelStrings().opus46:
return 'Opus 4.6'
return 'Opus 4.7'
case getModelStrings().opus46 + '[1m]':
return 'Opus 4.6 (1M context)'
return 'Opus 4.7 (1M context)'
case getModelStrings().opus45:
return 'Opus 4.5'
case getModelStrings().opus41:
@ -527,7 +527,7 @@ export function resolveSkillModelOverride(
if (has1mContext(skillModel) || !has1mContext(currentModel)) {
return skillModel
}
// modelSupports1M matches on canonical IDs ('claude-opus-4-6', 'claude-sonnet-4');
// modelSupports1M matches on canonical IDs ('claude-opus-4-7', 'claude-sonnet-4');
// a bare 'opus' alias falls through getCanonicalName unmatched. Resolve first.
if (modelSupports1M(parseUserSpecifiedModel(skillModel))) {
return skillModel + '[1m]'
@ -576,8 +576,8 @@ export function getMarketingNameForModel(modelId: string): string | undefined {
const has1m = modelId.toLowerCase().includes('[1m]')
const canonical = getCanonicalName(modelId)
if (canonical.includes('claude-opus-4-6')) {
return has1m ? 'Opus 4.6 (with 1M context)' : 'Opus 4.6'
if (canonical.includes('claude-opus-4-7')) {
return has1m ? 'Opus 4.7 (with 1M context)' : 'Opus 4.7'
}
if (canonical.includes('claude-opus-4-5')) {
return 'Opus 4.5'

View File

@ -11,7 +11,7 @@ function modelBelongsToFamily(model: string, family: string): boolean {
if (model.includes(family)) {
return true
}
// Resolve aliases like "best" → "claude-opus-4-6" to check family membership
// Resolve aliases like "best" → "claude-opus-4-7" to check family membership
if (isModelAlias(model)) {
const resolved = parseUserSpecifiedModel(model).toLowerCase()
return resolved.includes(family)

View File

@ -135,8 +135,8 @@ function getOpus46Option(fastMode = false): ModelOption {
return {
value: is3P ? getModelStrings().opus46 : 'opus',
label: 'Opus',
description: `Opus 4.6 · Most capable for complex work${getOpus46PricingSuffix(fastMode)}`,
descriptionForModel: 'Opus 4.6 - most capable for complex work',
description: `Opus 4.7 · Most capable for complex work${getOpus46PricingSuffix(fastMode)}`,
descriptionForModel: 'Opus 4.7 - most capable for complex work',
}
}
@ -156,9 +156,9 @@ export function getOpus46_1MOption(fastMode = false): ModelOption {
return {
value: is3P ? getModelStrings().opus46 + '[1m]' : 'opus[1m]',
label: 'Opus (1M context)',
description: `Opus 4.6 for long sessions${getOpus46PricingSuffix(fastMode)}`,
description: `Opus 4.7 for long sessions${getOpus46PricingSuffix(fastMode)}`,
descriptionForModel:
'Opus 4.6 with 1M context window - for long sessions with large codebases',
'Opus 4.7 with 1M context window - for long sessions with large codebases',
}
}
@ -212,7 +212,7 @@ function getMaxOpusOption(fastMode = false): ModelOption {
return {
value: 'opus',
label: 'Opus',
description: `Opus 4.6 · Most capable for complex work${fastMode ? getOpus46PricingSuffix(true) : ''}`,
description: `Opus 4.7 · Most capable for complex work${fastMode ? getOpus46PricingSuffix(true) : ''}`,
}
}
@ -231,7 +231,7 @@ export function getMaxOpus46_1MOption(fastMode = false): ModelOption {
return {
value: 'opus[1m]',
label: 'Opus (1M context)',
description: `Opus 4.6 with 1M context${billingInfo}${getOpus46PricingSuffix(fastMode)}`,
description: `Opus 4.7 with 1M context${billingInfo}${getOpus46PricingSuffix(fastMode)}`,
}
}
@ -240,9 +240,9 @@ function getMergedOpus1MOption(fastMode = false): ModelOption {
return {
value: is3P ? getModelStrings().opus46 + '[1m]' : 'opus[1m]',
label: 'Opus (1M context)',
description: `Opus 4.6 with 1M context · Most capable for complex work${!is3P && fastMode ? getOpus46PricingSuffix(fastMode) : ''}`,
description: `Opus 4.7 with 1M context · Most capable for complex work${!is3P && fastMode ? getOpus46PricingSuffix(fastMode) : ''}`,
descriptionForModel:
'Opus 4.6 with 1M context - most capable for complex work',
'Opus 4.7 with 1M context - most capable for complex work',
}
}
@ -262,7 +262,7 @@ function getOpusPlanOption(): ModelOption {
return {
value: 'opusplan',
label: 'Opus Plan Mode',
description: 'Use Opus 4.6 in plan mode, Sonnet 4.6 otherwise',
description: 'Use Opus 4.7 in plan mode, Sonnet 4.6 otherwise',
}
}
@ -323,7 +323,7 @@ function getModelOptionsBase(fastMode = false): ModelOption[] {
return standardOptions
}
// PAYG 1P API: Default (Sonnet) + Sonnet 1M + Opus 4.6 + Opus 1M + Haiku
// PAYG 1P API: Default (Sonnet) + Sonnet 1M + Opus 4.7 + Opus 1M + Haiku
if (getAPIProvider() === 'firstParty') {
const payg1POptions = [getDefaultOptionForUser(fastMode)]
if (checkSonnet1mAccess()) {
@ -341,7 +341,7 @@ function getModelOptionsBase(fastMode = false): ModelOption[] {
return payg1POptions
}
// PAYG 3P: Default (Sonnet 4.5) + Sonnet (3P custom) or Sonnet 4.6/1M + Opus (3P custom) or Opus 4.1/Opus 4.6/Opus1M + Haiku + Opus 4.1
// PAYG 3P: Default (Sonnet 4.5) + Sonnet (3P custom) or Sonnet 4.6/1M + Opus (3P custom) or Opus 4.1/Opus 4.7/Opus1M + Haiku + Opus 4.1
const payg3pOptions = [getDefaultOptionForUser(fastMode)]
const customSonnet = getCustomSonnetOption()
@ -359,7 +359,7 @@ function getModelOptionsBase(fastMode = false): ModelOption[] {
if (customOpus !== undefined) {
payg3pOptions.push(customOpus)
} else {
// Add Opus 4.1, Opus 4.6 and Opus 4.6 1M
// Add Opus 4.1, Opus 4.7 and Opus 4.7 1M
payg3pOptions.push(getOpus41Option()) // This is the default opus
payg3pOptions.push(getOpus46Option(fastMode))
if (checkOpus1mAccess()) {

View File

@ -43,8 +43,8 @@ async function getBedrockModelStrings(): Promise<ModelStrings> {
return fallback
}
// Each config's firstParty ID is the canonical substring we search for in the
// user's inference profile list (e.g. "claude-opus-4-6" matches
// "eu.anthropic.claude-opus-4-6-v1"). Fall back to the hardcoded bedrock ID
// user's inference profile list (e.g. "claude-opus-4-7" matches
// "eu.anthropic.claude-opus-4-7-v1"). Fall back to the hardcoded bedrock ID
// when no matching profile is found.
const out = {} as ModelStrings
for (const key of MODEL_KEYS) {
@ -57,7 +57,7 @@ async function getBedrockModelStrings(): Promise<ModelStrings> {
/**
* Layer user-configured modelOverrides (from settings.json) on top of the
* provider-derived model strings. Overrides are keyed by canonical first-party
* model ID (e.g. "claude-opus-4-6") and map to arbitrary provider-specific
* model ID (e.g. "claude-opus-4-7") and map to arbitrary provider-specific
* strings typically Bedrock inference profile ARNs.
*/
function applyModelOverrides(ms: ModelStrings): ModelStrings {

View File

@ -59,7 +59,7 @@ export const COST_TIER_5_25 = {
webSearchRequests: 0.01,
} as const satisfies ModelCosts
// Fast mode pricing for Opus 4.6: $30 input / $150 output per Mtok
// Fast mode pricing for Opus 4.7: $30 input / $150 output per Mtok
export const COST_TIER_30_150 = {
inputTokens: 30,
outputTokens: 150,
@ -89,7 +89,7 @@ export const COST_HAIKU_45 = {
const DEFAULT_UNKNOWN_MODEL_COST = COST_TIER_5_25
/**
* Get the cost tier for Opus 4.6 based on fast mode.
* Get the cost tier for Opus 4.7 based on fast mode.
*/
export function getOpus46CostTier(fastMode: boolean): ModelCosts {
if (isFastModeEnabled() && fastMode) {
@ -144,7 +144,7 @@ function tokensToUSDCost(modelCosts: ModelCosts, usage: Usage): number {
export function getModelCosts(model: string, usage: Usage): ModelCosts {
const shortName = getCanonicalName(model)
// Check if this is an Opus 4.6 model with fast mode active.
// Check if this is an Opus 4.7 model with fast mode active.
if (
shortName === firstPartyNameToCanonical(CLAUDE_OPUS_4_6_CONFIG.firstParty)
) {

View File

@ -74,7 +74,7 @@ export type PewterLedgerVariant = 'trim' | 'cut' | 'cap' | null
* guidance on plan file size.
*
* Baseline (control, 14d ending 2026-03-02, N=26.3M):
* p50 4,906 chars | p90 11,617 | mean 6,207 | 82% Opus 4.6
* p50 4,906 chars | p90 11,617 | mean 6,207 | 82% Opus 4.7
* Reject rate monotonic with size: 20% at <2K 50% at 20K+
*
* Primary: session-level Avg Cost (fact__201omjcij85f) Opus output is

View File

@ -392,7 +392,7 @@ export const SettingsSchema = lazySchema(() =>
.record(z.string(), z.string())
.optional()
.describe(
'Override mapping from Anthropic model ID (e.g. "claude-opus-4-6") to provider-specific ' +
'Override mapping from Anthropic model ID (e.g. "claude-opus-4-7") to provider-specific ' +
'model ID (e.g. a Bedrock inference profile ARN). Typically set in managed settings by ' +
'enterprise administrators.',
),

View File

@ -3,7 +3,7 @@ import { getAPIProvider } from '../model/providers.js'
// @[MODEL LAUNCH]: Update the fallback model below.
// When the user has never set teammateDefaultModel in /config, new teammates
// use Opus 4.6. Must be provider-aware so Bedrock/Vertex/Foundry customers get
// use Opus 4.7. Must be provider-aware so Bedrock/Vertex/Foundry customers get
// the correct model ID.
export function getHardcodedTeammateModelFallback(): string {
return CLAUDE_OPUS_4_6_CONFIG[getAPIProvider()]

View File

@ -63,9 +63,9 @@ GOOD:
BAD (never write these):
- "Fix bug found while testing with Claude Capybara"
- "1-shotted by claude-opus-4-6"
- "1-shotted by claude-opus-4-7"
- "Generated with Claude Code"
- "Co-Authored-By: Claude Opus 4.6 <…>"
- "Co-Authored-By: Claude Opus 4.7 <…>"
`
}
return ''