diff --git a/web/src/components/AssistantChat/modelOptions.test.ts b/web/src/components/AssistantChat/modelOptions.test.ts index 438a0cc6..4b01e1e3 100644 --- a/web/src/components/AssistantChat/modelOptions.test.ts +++ b/web/src/components/AssistantChat/modelOptions.test.ts @@ -89,7 +89,7 @@ describe('getModelOptionsForFlavor', () => { it('returns only default/current for cursor before models are discovered (no claude fallback)', () => { const options = getModelOptionsForFlavor('cursor', 'composer-2.5') expect(options).toEqual([ - { value: null, label: 'Default' }, + { value: null, label: 'Auto' }, { value: 'composer-2.5', label: 'composer-2.5' } ]) }) @@ -108,12 +108,12 @@ describe('getModelOptionsForFlavor', () => { it('does not inject raw wire id when dual picker base is already listed', () => { const wire = 'claude-opus-4-8[thinking=true,context=300k,effort=high,fast=false]' const options = getModelOptionsForFlavor('cursor', wire, [ - { value: null, label: 'Default' }, + { value: null, label: 'Auto' }, { value: 'claude-opus-4-8', label: 'Claude Opus 4.8' }, { value: 'composer-2.5', label: 'Composer 2.5' }, ]) expect(options).toEqual([ - { value: null, label: 'Default' }, + { value: null, label: 'Auto' }, { value: 'claude-opus-4-8', label: 'Claude Opus 4.8' }, { value: 'composer-2.5', label: 'Composer 2.5' }, ]) @@ -122,11 +122,11 @@ describe('getModelOptionsForFlavor', () => { it('injects unknown wire id only when catalog lacks base and wire', () => { const wire = 'claude-opus-4-9[effort=high,fast=false]' const options = getModelOptionsForFlavor('cursor', wire, [ - { value: null, label: 'Default' }, + { value: null, label: 'Auto' }, { value: 'composer-2.5', label: 'Composer 2.5' }, ]) expect(options).toEqual([ - { value: null, label: 'Default' }, + { value: null, label: 'Auto' }, { value: wire, label: wire }, { value: 'composer-2.5', label: 'Composer 2.5' }, ]) diff --git a/web/src/components/AssistantChat/modelOptions.ts b/web/src/components/AssistantChat/modelOptions.ts index 7e4aed68..0f017fec 100644 --- a/web/src/components/AssistantChat/modelOptions.ts +++ b/web/src/components/AssistantChat/modelOptions.ts @@ -1,4 +1,5 @@ import { MODEL_OPTIONS } from '@/components/NewSession/types' +import { CURSOR_AUTO_MODEL_LABEL } from '@/lib/cursorModelOptions' import { getClaudeComposerModelOptions, getNextClaudeComposerModel } from './claudeModelOptions' import type { ClaudeComposerModelOption } from './claudeModelOptions' @@ -120,7 +121,7 @@ export function getModelOptionsForFlavor( return [] } if (flavor === 'cursor') { - return withCurrentModelOption([{ value: null, label: 'Default' }], currentModel) + return withCurrentModelOption([{ value: null, label: CURSOR_AUTO_MODEL_LABEL }], currentModel) } // Kimi has no predefined model list — show just the auto/default option. if (flavor === 'kimi') { diff --git a/web/src/components/NewSession/newSessionCursorModels.test.ts b/web/src/components/NewSession/newSessionCursorModels.test.ts index 07e354ad..1c574074 100644 --- a/web/src/components/NewSession/newSessionCursorModels.test.ts +++ b/web/src/components/NewSession/newSessionCursorModels.test.ts @@ -97,7 +97,7 @@ describe('flat vs dual cursor model pickers', () => { const options = buildNewSessionCursorModelOptions(picker) expect(picker.mode).toBe('flat') expect(options).toEqual([ - { value: 'auto', label: 'Default' }, + { value: 'auto', label: 'Auto' }, { value: 'claude-opus-4-7[thinking=true,context=300k,effort=xhigh,fast=false]', label: 'claude-opus-4-7 · thinking=true,context=300k,effort=xhigh,fast=false' @@ -110,7 +110,7 @@ describe('flat vs dual cursor model pickers', () => { const picker = buildNewSessionCursorPickerState([...acpModels], 'auto') expect(picker.mode).toBe('dual') expect(buildNewSessionCursorModelOptions(picker)).toEqual([ - { value: 'auto', label: 'Default' }, + { value: 'auto', label: 'Auto' }, { value: 'composer-2.5', label: 'composer-2.5' }, ]) }) @@ -154,7 +154,7 @@ describe('probe slug catalog (New Session cold start)', () => { ] const picker = buildNewSessionCursorPickerState(probeOnly, 'composer-2.5') expect(picker.mode).toBe('flat') - expect(picker.modelOptions).toEqual([{ value: 'auto', label: 'Default' }]) + expect(picker.modelOptions).toEqual([{ value: 'auto', label: 'Auto' }]) expect(picker.effortOptions).toEqual([]) expect(shouldShowCursorModelsUnavailable({ agent: 'cursor', @@ -169,7 +169,7 @@ describe('new session cursor model options', () => { it('maps base options with auto default and raw variant labels', () => { const picker = buildNewSessionCursorPickerState([...acpModels], 'composer-2.5[fast=true]') expect(buildNewSessionCursorModelOptions(picker)).toEqual([ - { value: 'auto', label: 'Default' }, + { value: 'auto', label: 'Auto' }, { value: 'composer-2.5', label: 'composer-2.5' }, ]) expect(buildNewSessionCursorEffortOptions(picker)).toEqual([ diff --git a/web/src/lib/cursorModelOptions.test.ts b/web/src/lib/cursorModelOptions.test.ts index 1f943c7b..5690b064 100644 --- a/web/src/lib/cursorModelOptions.test.ts +++ b/web/src/lib/cursorModelOptions.test.ts @@ -3,6 +3,7 @@ import { buildCursorEffortPickerOptions, buildCursorModelCatalog, buildFlatCursorModelPickerOptions, + CURSOR_AUTO_MODEL_LABEL, cursorCatalogHasMultiVariantBases, shouldUseCursorDualPickers, cursorEffortPickerLabel, @@ -56,7 +57,7 @@ describe('buildCursorModelCatalog', () => { it('groups exact ACP wire variants by raw base id and sorts model bases', () => { const catalog = buildCursorModelCatalog([...acpModels]) expect(catalog.baseOptions.map((o) => o.label)).toEqual([ - 'Default', + CURSOR_AUTO_MODEL_LABEL, 'claude-opus-4-8', 'composer-2.5', ]) @@ -102,7 +103,7 @@ describe('picker labels and modes', () => { ], { defaultValue: 'auto' }) expect(cursorCatalogHasMultiVariantBases(catalog)).toBe(false) expect(buildFlatCursorModelPickerOptions(catalog, { defaultValue: 'auto' })).toEqual([ - { value: 'auto', label: 'Default' }, + { value: 'auto', label: CURSOR_AUTO_MODEL_LABEL }, { value: 'claude-opus-4-7[thinking=true,context=300k,effort=xhigh,fast=false]', label: 'claude-opus-4-7 · thinking=true,context=300k,effort=xhigh,fast=false' @@ -129,7 +130,7 @@ describe('picker labels and modes', () => { { modelId: 'composer-2.5[fast=false]', name: 'Composer 2.5' }, ], { defaultValue: 'auto' }) expect(buildFlatCursorModelPickerOptions(catalog, { defaultValue: 'auto' })).toEqual([ - { value: 'auto', label: 'Default' }, + { value: 'auto', label: CURSOR_AUTO_MODEL_LABEL }, { value: 'composer-2.5[fast=true]', label: 'fast=true' }, { value: 'composer-2.5[fast=false]', label: 'fast=false' }, ]) diff --git a/web/src/lib/cursorModelOptions.ts b/web/src/lib/cursorModelOptions.ts index 3d71c698..d871a13e 100644 --- a/web/src/lib/cursorModelOptions.ts +++ b/web/src/lib/cursorModelOptions.ts @@ -15,6 +15,9 @@ export type CursorModelCatalog = { wireToBase: Map } +/** User-facing label for Cursor automatic model selection (`auto` / ACP `default[]`). */ +export const CURSOR_AUTO_MODEL_LABEL = 'Auto' + /** Base model id before ACP wire suffix, e.g. `composer-2.5[fast=true]` → `composer-2.5`. */ export function cursorModelBaseId(modelId: string): string { const trimmed = modelId.trim() @@ -134,7 +137,7 @@ export function cursorVariantDisambiguationSuffix(modelId: string): string { /** * Group ACP wire ids by raw base model. Labels are raw base ids; variant labels are raw suffixes. - * Catalog order follows the input order; only `Default` is prepended. + * Catalog order follows the input order; only "Auto" is prepended. */ export function buildCursorModelCatalog( availableModels: readonly CursorModelSummary[], @@ -185,7 +188,7 @@ export function buildCursorModelCatalog( .sort((a, b) => a[1].localeCompare(b[1], undefined, { sensitivity: 'base' })) const baseOptions: CursorModelOption[] = [ - { value: defaultValue, label: 'Default' }, + { value: defaultValue, label: CURSOR_AUTO_MODEL_LABEL }, ...sortedBaseEntries.map(([baseId, label]) => ({ value: baseId, label })) ] @@ -312,7 +315,7 @@ export function buildFlatCursorModelPickerOptions( } return [ - { value: defaultValue ?? 'auto', label: 'Default' }, + { value: defaultValue ?? 'auto', label: CURSOR_AUTO_MODEL_LABEL }, ...rows ] } diff --git a/web/src/lib/locales/en.ts b/web/src/lib/locales/en.ts index 112a620e..67342506 100644 --- a/web/src/lib/locales/en.ts +++ b/web/src/lib/locales/en.ts @@ -269,7 +269,7 @@ export default { 'newSession.model.optional': 'optional', 'newSession.model.loadFailed': 'Failed to load models', 'newSession.model.selectVariant': 'Select variant', - 'newSession.model.cursorUnavailable': 'No Cursor models yet. Start a Cursor session once, or use Default.', + 'newSession.model.cursorUnavailable': 'No Cursor models yet. Start a Cursor session once, or use Auto.', 'newSession.opencodeModel.loading': 'Discovering OpenCode models…', 'newSession.opencodeModel.loadFailed': 'Failed to load OpenCode models', 'newSession.opencodeModel.retry': 'Retry', diff --git a/web/src/lib/locales/zh-CN.ts b/web/src/lib/locales/zh-CN.ts index 0378dc6e..499fdfdc 100644 --- a/web/src/lib/locales/zh-CN.ts +++ b/web/src/lib/locales/zh-CN.ts @@ -273,7 +273,7 @@ export default { 'newSession.model.optional': '可选', 'newSession.model.loadFailed': '加载模型失败', 'newSession.model.selectVariant': '选择变体', - 'newSession.model.cursorUnavailable': '暂无 Cursor 模型列表。请先运行一次 Cursor 会话,或使用默认模型。', + 'newSession.model.cursorUnavailable': '暂无 Cursor 模型列表。请先运行一次 Cursor 会话,或使用 Auto。', 'newSession.opencodeModel.loading': '正在发现 OpenCode 模型…', 'newSession.opencodeModel.loadFailed': '加载 OpenCode 模型失败', 'newSession.opencodeModel.retry': '重试',