fix(desktop): show the real effort on the composer pill

The pill hardcoded 'Med' whenever the surface had no explicit effort, so
a profile configured for high advertised a level the agent would not
use. Take the profile default as a fallback and drop the now-unused
shell.modelMenu.medium key across the locales.
This commit is contained in:
Brooklyn Nicholson 2026-07-25 20:37:13 -05:00
parent e2122f22b8
commit be1edef5ce
9 changed files with 25 additions and 19 deletions

View file

@ -11,7 +11,7 @@ import { useI18n } from '@/i18n'
import { ChevronDown } from '@/lib/icons'
import { formatModelStatusLabel } from '@/lib/model-status-label'
import { cn } from '@/lib/utils'
import { $currentModelSource, setModelPickerOpen } from '@/store/session'
import { $currentModelSource, $defaultReasoningEffort, setModelPickerOpen } from '@/store/session'
import type { ChatBarState } from './types'
@ -48,6 +48,7 @@ export function ModelPill({
const fastMode = useStore(view.$fast)
const reasoningEffort = useStore(view.$reasoningEffort)
const modelSource = useStore($currentModelSource)
const defaultEffort = useStore($defaultReasoningEffort)
const runtimeId = useStore(view.$runtimeId)
const [open, setOpen] = useState(false)
@ -68,7 +69,9 @@ export function ModelPill({
) : (
<>
{currentModel.trim() ? (
<span className="truncate">{formatModelStatusLabel(currentModel, { fastMode, reasoningEffort })}</span>
<span className="truncate">
{formatModelStatusLabel(currentModel, { defaultEffort, fastMode, reasoningEffort })}
</span>
) : (
<GlyphSpinner className="opacity-50" spinner="braille" />
)}

View file

@ -1986,8 +1986,7 @@ export const ar = defineLocale({
noModels: 'لا توجد نماذج',
editModels: 'تحرير النماذج',
refreshModels: 'تحديث النماذج',
fast: 'سريع',
medium: 'متوسط'
fast: 'سريع'
},
modelOptions: {
noOptions: 'لا توجد خيارات لهذا النموذج',

View file

@ -2306,8 +2306,7 @@ export const en: Translations = {
noModels: 'No models found',
editModels: 'Edit Models…',
refreshModels: 'Refresh Models',
fast: 'Fast',
medium: 'Med'
fast: 'Fast'
},
modelOptions: {
noOptions: 'No options for this model',

View file

@ -2178,8 +2178,7 @@ export const ja = defineLocale({
noModels: 'モデルが見つかりません',
editModels: 'モデルを編集…',
refreshModels: 'モデルを更新',
fast: '高速',
medium: '中'
fast: '高速'
},
modelOptions: {
noOptions: 'このモデルにはオプションがありません',

View file

@ -1915,7 +1915,6 @@ export interface Translations {
editModels: string
refreshModels: string
fast: string
medium: string
}
modelOptions: {
noOptions: string

View file

@ -2105,8 +2105,7 @@ export const zhHant = defineLocale({
noModels: '找不到模型',
editModels: '編輯模型…',
refreshModels: '重新整理模型',
fast: '快速',
medium: '中'
fast: '快速'
},
modelOptions: {
noOptions: '此模型沒有可用選項',

View file

@ -2483,8 +2483,7 @@ export const zh: Translations = {
noModels: '未找到模型',
editModels: '编辑模型…',
refreshModels: '刷新模型',
fast: '快速',
medium: '中'
fast: '快速'
},
modelOptions: {
noOptions: '此模型没有可用选项',

View file

@ -34,9 +34,16 @@ describe('model-status-label', () => {
)
})
it('always surfaces the effort (default medium) so the level is visible', () => {
it('falls back to the profile default effort, then to medium', () => {
expect(formatModelStatusLabel('openai/gpt-5.5', { reasoningEffort: 'medium' })).toBe('GPT-5.5 · Med')
expect(formatModelStatusLabel('openai/gpt-5.5')).toBe('GPT-5.5 · Med')
// No session-level effort → the configured profile default is advertised,
// not Hermes' built-in medium.
expect(formatModelStatusLabel('openai/gpt-5.5', { defaultEffort: 'high' })).toBe('GPT-5.5 · High')
// An explicit session effort still wins over the profile default.
expect(formatModelStatusLabel('openai/gpt-5.5', { defaultEffort: 'high', reasoningEffort: 'low' })).toBe(
'GPT-5.5 · Low'
)
})
it('returns just the placeholder name when there is no model', () => {

View file

@ -99,10 +99,12 @@ export function displayModelName(model: string): string {
return modelDisplayParts(model).name
}
/** Status bar trigger label — model name plus the live session state (effort/fast). */
/** Status bar trigger label model name plus the live session state (effort/fast).
* `defaultEffort` is the profile's configured level, used when the surface has
* no explicit effort so the label never advertises a default the agent won't use. */
export function formatModelStatusLabel(
model: string,
options?: { fastMode?: boolean; reasoningEffort?: string }
options?: { defaultEffort?: string; fastMode?: boolean; reasoningEffort?: string }
): string {
const name = displayModelName(model)
@ -118,9 +120,9 @@ export function formatModelStatusLabel(
parts.push('Fast')
}
// Always surface the effort (empty = Hermes default of medium) so the
// current reasoning level is visible at a glance, not just when non-default.
parts.push(reasoningEffortLabel(options?.reasoningEffort ?? '') || 'Med')
// Always surface the effort so the current reasoning level is visible at a
// glance, not just when non-default.
parts.push(reasoningEffortLabel(options?.reasoningEffort || options?.defaultEffort || 'medium'))
return `${name} · ${parts.join(' ')}`
}