diff --git a/apps/web/src/components/chat/TraitsPicker.test.ts b/apps/web/src/components/chat/TraitsPicker.test.ts index 93157490090..0cb199d64ba 100644 --- a/apps/web/src/components/chat/TraitsPicker.test.ts +++ b/apps/web/src/components/chat/TraitsPicker.test.ts @@ -1,10 +1,10 @@ import { describe, expect, it } from "vite-plus/test"; -import type { ProviderOptionDescriptor } from "@t3tools/contracts"; +import { ProviderDriverKind, type ProviderOptionDescriptor } from "@t3tools/contracts"; import { buildTraitsTriggerDisplay } from "./TraitsPicker"; function selectDescriptor( id: string, - options: ReadonlyArray<{ id: string; label: string }>, + options: ReadonlyArray<{ id: string; label: string; isDefault?: boolean }>, currentValue: string, ): Extract { return { id, label: id, type: "select", options: [...options], currentValue }; @@ -17,7 +17,7 @@ function fastModeDescriptor( } const EFFORT = selectDescriptor( - "effort", + "reasoningEffort", [ { id: "high", label: "High" }, { id: "max", label: "Max" }, @@ -33,10 +33,13 @@ const CONTEXT_WINDOW = selectDescriptor( "1m", ); +const CODEX = ProviderDriverKind.make("codex"); + function display(descriptors: ReadonlyArray, fastModeEnabled: boolean) { return buildTraitsTriggerDisplay({ + provider: CODEX, descriptors, - primarySelectDescriptorId: "effort", + primarySelectDescriptorId: "reasoningEffort", ultrathinkPromptControlled: false, fastModeEnabled, }); @@ -57,6 +60,16 @@ describe("buildTraitsTriggerDisplay", () => { }); }); + it("omits Codex's default Standard tier beside reasoning", () => { + const serviceTier = selectDescriptor( + "serviceTier", + [{ id: "default", label: "Standard", isDefault: true }], + "default", + ); + + expect(display([EFFORT, serviceTier], false).label).toBe("High"); + }); + it("keeps non-fastMode booleans as text labels", () => { const thinking: Extract = { id: "thinking", @@ -100,8 +113,9 @@ describe("buildTraitsTriggerDisplay", () => { it("still renders the prompt-controlled ultrathink label alongside the bolt", () => { expect( buildTraitsTriggerDisplay({ + provider: CODEX, descriptors: [EFFORT, fastModeDescriptor(true)], - primarySelectDescriptorId: "effort", + primarySelectDescriptorId: "reasoningEffort", ultrathinkPromptControlled: true, fastModeEnabled: true, }), diff --git a/apps/web/src/components/chat/TraitsPicker.tsx b/apps/web/src/components/chat/TraitsPicker.tsx index df429e7aca2..f95f3a4c08a 100644 --- a/apps/web/src/components/chat/TraitsPicker.tsx +++ b/apps/web/src/components/chat/TraitsPicker.tsx @@ -388,6 +388,7 @@ export const TraitsMenuContent = memo(function TraitsMenuContentImpl({ * chevron) would leave the trigger unreadable. */ export function buildTraitsTriggerDisplay(input: { + provider: ProviderDriverKind; descriptors: ReadonlyArray; primarySelectDescriptorId: string | null; ultrathinkPromptControlled: boolean; @@ -400,6 +401,18 @@ export function buildTraitsTriggerDisplay(input: { hasFastMode = true; continue; } + if ( + input.provider === "codex" && + descriptor.id === "serviceTier" && + descriptor.type === "select" && + input.descriptors.some(({ id }) => id === "reasoningEffort") + ) { + const currentValue = getProviderOptionCurrentValue(descriptor); + const currentOption = descriptor.options.find((option) => option.id === currentValue); + if (currentOption?.id === "default" && currentOption.isDefault === true) { + continue; + } + } const label = input.ultrathinkPromptControlled && descriptor.id === input.primarySelectDescriptorId ? "Ultrathink" @@ -457,6 +470,7 @@ export const TraitsPicker = memo(function TraitsPicker({ } const { label: triggerLabel, showFastModeIcon } = buildTraitsTriggerDisplay({ + provider, descriptors, primarySelectDescriptorId: primarySelectDescriptor?.id ?? null, ultrathinkPromptControlled,