| ... | @@ -396,10 +396,11 @@ export const TraitsMenuContent = memo(function TraitsMenuContentImpl({ | ... | @@ -396,10 +396,11 @@ export const TraitsMenuContent = memo(function TraitsMenuContentImpl({ |
| 396 | | 396 | |
| 397 | /** | 397 | /** |
| 398 | * Build the traits trigger's text label plus whether the fast-mode bolt should | 398 | * Build the traits trigger's text label plus whether the fast-mode bolt should |
| 399 | * render. Fast mode is a lightning bolt when on and nothing at all when off — | 399 | * render. Claude and Cursor expose fast mode as a boolean, while Codex exposes |
| 400 | * "Normal" is the near-universal case and isn't worth the horizontal space. The | 400 | * it through the Standard/Fast service tiers. In either form, fast mode is a |
| 401 | * one exception is when fast mode is the only trait, where a bare bolt (or bare | 401 | * lightning bolt when on and nothing at all when off. The one exception is when |
| 402 | * chevron) would leave the trigger unreadable. | 402 | * fast mode is the only trait, where a bare bolt (or bare chevron) would leave |
| | 403 | * the trigger unreadable. |
| 403 | */ | 404 | */ |
| 404 | export function buildTraitsTriggerDisplay(input: { | 405 | export function buildTraitsTriggerDisplay(input: { |
| 405 | provider: ProviderDriverKind; | 406 | provider: ProviderDriverKind; |
| ... | @@ -407,13 +408,13 @@ export function buildTraitsTriggerDisplay(input: { | ... | @@ -407,13 +408,13 @@ export function buildTraitsTriggerDisplay(input: { |
| 407 | primarySelectDescriptorId: string | null; | 408 | primarySelectDescriptorId: string | null; |
| 408 | ultrathinkPromptControlled: boolean; | 409 | ultrathinkPromptControlled: boolean; |
| 409 | }): { label: string; showFastModeIcon: boolean } { | 410 | }): { label: string; showFastModeIcon: boolean } { |
| 410 | let hasFastMode = false; | 411 | let fastModeFallbackLabel: string | null = null; |
| 411 | let fastModeEnabled = false; | 412 | let fastModeEnabled = false; |
| 412 | const labels: Array<string> = []; | 413 | const labels: Array<string> = []; |
| 413 | for (const descriptor of input.descriptors) { | 414 | for (const descriptor of input.descriptors) { |
| 414 | if (descriptor.id === "fastMode" && descriptor.type === "boolean") { | 415 | if (descriptor.id === "fastMode" && descriptor.type === "boolean") { |
| 415 | hasFastMode = true; | | |
| 416 | fastModeEnabled = descriptor.currentValue === true; | 416 | fastModeEnabled = descriptor.currentValue === true; |
| | 417 | fastModeFallbackLabel = fastModeEnabled ? "Fast" : "Normal"; |
| 417 | continue; | 418 | continue; |
| 418 | } | 419 | } |
| 419 | if ( | 420 | if ( |
| ... | @@ -424,8 +425,10 @@ export function buildTraitsTriggerDisplay(input: { | ... | @@ -424,8 +425,10 @@ export function buildTraitsTriggerDisplay(input: { |
| 424 | const currentValue = getProviderOptionCurrentValue(descriptor); | 425 | const currentValue = getProviderOptionCurrentValue(descriptor); |
| 425 | const fastTier = descriptor.options.find(({ label }) => label === "Fast"); | 426 | const fastTier = descriptor.options.find(({ label }) => label === "Fast"); |
| 426 | if (fastTier && (currentValue === "default" || currentValue === fastTier.id)) { | 427 | if (fastTier && (currentValue === "default" || currentValue === fastTier.id)) { |
| 427 | hasFastMode = true; | | |
| 428 | fastModeEnabled = currentValue === fastTier.id; | 428 | fastModeEnabled = currentValue === fastTier.id; |
| | 429 | fastModeFallbackLabel = |
| | 430 | descriptor.options.find(({ id }) => id === currentValue)?.label ?? |
| | 431 | (fastModeEnabled ? "Fast" : "Normal"); |
| 429 | continue; | 432 | continue; |
| 430 | } | 433 | } |
| 431 | } | 434 | } |
| ... | @@ -443,8 +446,8 @@ export function buildTraitsTriggerDisplay(input: { | ... | @@ -443,8 +446,8 @@ export function buildTraitsTriggerDisplay(input: { |
| 443 | // Only fall back to text when fast mode is genuinely the sole trait. Keying | 446 | // Only fall back to text when fast mode is genuinely the sole trait. Keying |
| 444 | // off an empty label list alone would also catch descriptors that resolved to | 447 | // off an empty label list alone would also catch descriptors that resolved to |
| 445 | // no label at all, printing a bogus "Normal" for a model without fast mode. | 448 | // no label at all, printing a bogus "Normal" for a model without fast mode. |
| 446 | if (labels.length === 0 && hasFastMode) { | 449 | if (labels.length === 0 && fastModeFallbackLabel !== null) { |
| 447 | return { label: fastModeEnabled ? "Fast" : "Normal", showFastModeIcon: false }; | 450 | return { label: fastModeFallbackLabel, showFastModeIcon: false }; |
| 448 | } | 451 | } |
| 449 | return { label: labels.join(" · "), showFastModeIcon: fastModeEnabled }; | 452 | return { label: labels.join(" · "), showFastModeIcon: fastModeEnabled }; |
| 450 | } | 453 | } |