Skip to content

Commit e49767d

Browse files
authored
Merge pull request #242 from musnows/codex/compact-model-capability-badges
[codex] Compact provider model capability badges
2 parents b868747 + 0c82bb1 commit e49767d

2 files changed

Lines changed: 59 additions & 33 deletions

File tree

src/renderer/src/components/settings-section-provider-models.test.ts

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,30 @@ describe('ProviderModelsManager', () => {
8181
expect(html).toContain('Default profile')
8282
})
8383

84+
it('keeps model names on a separate row from compact capability badges', () => {
85+
const html = renderManager(provider({
86+
models: ['deepseek-v4-pro'],
87+
modelProfiles: {
88+
'deepseek-v4-pro': {
89+
contextWindowTokens: 1_000_000,
90+
inputModalities: ['text', 'image'],
91+
outputModalities: ['text'],
92+
supportsToolCalling: true,
93+
messageParts: ['text', 'image_url'],
94+
reasoning: {
95+
supportedEfforts: ['off', 'high'],
96+
defaultEffort: 'high',
97+
requestProtocol: 'deepseek-chat-completions'
98+
}
99+
}
100+
}
101+
}))
102+
103+
expect(html).toContain('grid min-w-0 flex-1 gap-1.5')
104+
expect(html).toContain('flex min-w-0 flex-wrap items-center gap-1')
105+
expect(html).toContain('text-[10.5px]')
106+
})
107+
84108
it('exposes the complete model name on hover for truncated rows', () => {
85109
const longModelId = 'MiniMax-Text-01-very-long-model-name-with-extra-tags-and-context'
86110
const html = renderManager(provider({ models: [longModelId] }))

src/renderer/src/components/settings-section-provider-models.tsx

Lines changed: 35 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -191,7 +191,7 @@ function ModelBadge({
191191
? 'border-ds-border-muted bg-transparent text-ds-faint'
192192
: 'border-ds-border-muted bg-ds-main/60 text-ds-muted'
193193
return (
194-
<span className={`inline-flex shrink-0 items-center gap-1 rounded-full border px-2 py-0.5 text-[11px] font-medium leading-4 ${toneClass}`}>
194+
<span className={`inline-flex shrink-0 items-center gap-0.5 rounded-full border px-1.5 py-0 text-[10.5px] font-medium leading-4 ${toneClass}`}>
195195
{icon}
196196
{children}
197197
</span>
@@ -200,7 +200,7 @@ function ModelBadge({
200200

201201
function ModelName({ modelId }: { modelId: string }): ReactElement {
202202
return (
203-
<span className="group/model-name relative min-w-0 flex-1" title={modelId}>
203+
<span className="group/model-name relative min-w-0" title={modelId}>
204204
<span className="block truncate font-mono text-[12.5px] text-ds-ink">{modelId}</span>
205205
<span
206206
aria-hidden="true"
@@ -310,41 +310,43 @@ export function ProviderModelsManager({
310310
return (
311311
<li
312312
key={modelEntryKey(kind, modelId)}
313-
className={`flex flex-wrap items-center gap-2 rounded-xl border px-3 py-2 ${
313+
className={`flex items-start gap-2 rounded-xl border px-3 py-2 ${
314314
active ? 'border-accent/60 bg-ds-main/45 ring-1 ring-accent/30' : 'border-ds-border bg-ds-card'
315315
}`}
316316
>
317-
<ModelName modelId={modelId} />
318-
<span className="flex flex-wrap items-center gap-1.5">
319-
<ModelBadge tone={kind === 'chat' ? 'faint' : 'muted'}>
320-
{t(modelKindLabelKey(kind))}
321-
</ModelBadge>
322-
{kind === 'chat' && profile ? (
323-
<>
324-
{profile.contextWindowTokens ? (
325-
<ModelBadge>{t('providerModelContextBadge', {
326-
size: describeContextWindowTokens(profile.contextWindowTokens)
327-
})}</ModelBadge>
328-
) : null}
329-
{profile.inputModalities.includes('image') ? (
330-
<ModelBadge icon={<Eye className="h-3 w-3" strokeWidth={1.9} />}>
331-
{t('modelProviderVisionBadge')}
332-
</ModelBadge>
333-
) : null}
334-
{profile.reasoning ? (
335-
<ModelBadge icon={<Brain className="h-3 w-3" strokeWidth={1.9} />}>
336-
{t('providerModelReasoningBadge')}
337-
</ModelBadge>
338-
) : null}
339-
{!profile.supportsToolCalling ? (
340-
<ModelBadge tone="warning">{t('providerModelNoToolsBadge')}</ModelBadge>
341-
) : null}
342-
</>
343-
) : kind === 'chat' ? (
344-
<ModelBadge tone="faint">{t('providerModelDefaultProfileBadge')}</ModelBadge>
345-
) : null}
317+
<span className="grid min-w-0 flex-1 gap-1.5">
318+
<ModelName modelId={modelId} />
319+
<span className="flex min-w-0 flex-wrap items-center gap-1">
320+
<ModelBadge tone={kind === 'chat' ? 'faint' : 'muted'}>
321+
{t(modelKindLabelKey(kind))}
322+
</ModelBadge>
323+
{kind === 'chat' && profile ? (
324+
<>
325+
{profile.contextWindowTokens ? (
326+
<ModelBadge>{t('providerModelContextBadge', {
327+
size: describeContextWindowTokens(profile.contextWindowTokens)
328+
})}</ModelBadge>
329+
) : null}
330+
{profile.inputModalities.includes('image') ? (
331+
<ModelBadge icon={<Eye className="h-2.5 w-2.5" strokeWidth={1.9} />}>
332+
{t('modelProviderVisionBadge')}
333+
</ModelBadge>
334+
) : null}
335+
{profile.reasoning ? (
336+
<ModelBadge icon={<Brain className="h-2.5 w-2.5" strokeWidth={1.9} />}>
337+
{t('providerModelReasoningBadge')}
338+
</ModelBadge>
339+
) : null}
340+
{!profile.supportsToolCalling ? (
341+
<ModelBadge tone="warning">{t('providerModelNoToolsBadge')}</ModelBadge>
342+
) : null}
343+
</>
344+
) : kind === 'chat' ? (
345+
<ModelBadge tone="faint">{t('providerModelDefaultProfileBadge')}</ModelBadge>
346+
) : null}
347+
</span>
346348
</span>
347-
<span className="flex items-center gap-1">
349+
<span className="flex shrink-0 items-center gap-1 pt-0.5">
348350
<button
349351
type="button"
350352
aria-label={t('providerModelEditAction', { model: modelId })}

0 commit comments

Comments
 (0)