| author | |
| committer | |
| log | 9146ed2f49a094aa8afee7d3a66987e2a82aaaf6 |
| tree | 1998debaf5e0b1e6fd9a96d702bbba344419ece1 |
| parent | f0f16e4f6e8e923dcb17fc1c25d4fb1e442f80a5 |
| signature | Signed by PGP key B5690EEEBB952194 |
2 files changed, 30 insertions(+), 24 deletions(-)
apps/web/src/components/chat/TraitsPicker.test.ts+20-12| ... | @@ -35,39 +35,48 @@ const CONTEXT_WINDOW = selectDescriptor( | ... | @@ -35,39 +35,48 @@ const CONTEXT_WINDOW = selectDescriptor( |
| 35 | 35 | ||
| 36 | const CODEX = ProviderDriverKind.make("codex"); | 36 | const CODEX = ProviderDriverKind.make("codex"); |
| 37 | 37 | ||
| 38 | function display(descriptors: ReadonlyArray<ProviderOptionDescriptor>, fastModeEnabled: boolean) { | 38 | function display(descriptors: ReadonlyArray<ProviderOptionDescriptor>) { |
| 39 | return buildTraitsTriggerDisplay({ | 39 | return buildTraitsTriggerDisplay({ |
| 40 | provider: CODEX, | 40 | provider: CODEX, |
| 41 | descriptors, | 41 | descriptors, |
| 42 | primarySelectDescriptorId: "reasoningEffort", | 42 | primarySelectDescriptorId: "reasoningEffort", |
| 43 | ultrathinkPromptControlled: false, | 43 | ultrathinkPromptControlled: false, |
| 44 | fastModeEnabled, | ||
| 45 | }); | 44 | }); |
| 46 | } | 45 | } |
| 47 | 46 | ||
| 48 | describe("buildTraitsTriggerDisplay", () => { | 47 | describe("buildTraitsTriggerDisplay", () => { |
| 49 | it("omits fast mode from the label entirely when it is off", () => { | 48 | it("omits fast mode from the label entirely when it is off", () => { |
| 50 | expect(display([EFFORT, fastModeDescriptor(false), CONTEXT_WINDOW], false)).toEqual({ | 49 | expect(display([EFFORT, fastModeDescriptor(false), CONTEXT_WINDOW])).toEqual({ |
| 51 | label: "High · 1M", | 50 | label: "High · 1M", |
| 52 | showFastModeIcon: false, | 51 | showFastModeIcon: false, |
| 53 | }); | 52 | }); |
| 54 | }); | 53 | }); |
| 55 | 54 | ||
| 56 | it("shows the bolt instead of a text label when fast mode is on", () => { | 55 | it("shows the bolt instead of a text label when fast mode is on", () => { |
| 57 | expect(display([EFFORT, fastModeDescriptor(true), CONTEXT_WINDOW], true)).toEqual({ | 56 | expect(display([EFFORT, fastModeDescriptor(true), CONTEXT_WINDOW])).toEqual({ |
| 58 | label: "High · 1M", | 57 | label: "High · 1M", |
| 59 | showFastModeIcon: true, | 58 | showFastModeIcon: true, |
| 60 | }); | 59 | }); |
| 61 | }); | 60 | }); |
| 62 | 61 | ||
| 63 | it("omits Codex's default Standard tier beside reasoning", () => { | 62 | it("renders Codex's Standard and Fast service tiers as fast mode", () => { |
| 64 | const serviceTier = selectDescriptor( | 63 | const serviceTier = selectDescriptor( |
| 65 | "serviceTier", | 64 | "serviceTier", |
| 66 | [{ id: "default", label: "Standard", isDefault: true }], | 65 | [ |
| 66 | { id: "default", label: "Standard", isDefault: true }, | ||
| 67 | { id: "priority", label: "Fast" }, | ||
| 68 | ], | ||
| 67 | "default", | 69 | "default", |
| 68 | ); | 70 | ); |
| 69 | 71 | ||
| 70 | expect(display([EFFORT, serviceTier], false).label).toBe("High"); | 72 | expect(display([EFFORT, serviceTier])).toEqual({ |
| 73 | label: "High", | ||
| 74 | showFastModeIcon: false, | ||
| 75 | }); | ||
| 76 | expect(display([EFFORT, { ...serviceTier, currentValue: "priority" }])).toEqual({ | ||
| 77 | label: "High", | ||
| 78 | showFastModeIcon: true, | ||
| 79 | }); | ||
| 71 | }); | 80 | }); |
| 72 | 81 | ||
| 73 | it("keeps non-fastMode booleans as text labels", () => { | 82 | it("keeps non-fastMode booleans as text labels", () => { |
| ... | @@ -77,18 +86,18 @@ describe("buildTraitsTriggerDisplay", () => { | ... | @@ -77,18 +86,18 @@ describe("buildTraitsTriggerDisplay", () => { |
| 77 | type: "boolean", | 86 | type: "boolean", |
| 78 | currentValue: true, | 87 | currentValue: true, |
| 79 | }; | 88 | }; |
| 80 | expect(display([EFFORT, thinking], false)).toEqual({ | 89 | expect(display([EFFORT, thinking])).toEqual({ |
| 81 | label: "High · Thinking On", | 90 | label: "High · Thinking On", |
| 82 | showFastModeIcon: false, | 91 | showFastModeIcon: false, |
| 83 | }); | 92 | }); |
| 84 | }); | 93 | }); |
| 85 | 94 | ||
| 86 | it("falls back to a text label when fast mode is the only trait", () => { | 95 | it("falls back to a text label when fast mode is the only trait", () => { |
| 87 | expect(display([fastModeDescriptor(true)], true)).toEqual({ | 96 | expect(display([fastModeDescriptor(true)])).toEqual({ |
| 88 | label: "Fast", | 97 | label: "Fast", |
| 89 | showFastModeIcon: false, | 98 | showFastModeIcon: false, |
| 90 | }); | 99 | }); |
| 91 | expect(display([fastModeDescriptor(false)], false)).toEqual({ | 100 | expect(display([fastModeDescriptor(false)])).toEqual({ |
| 92 | label: "Normal", | 101 | label: "Normal", |
| 93 | showFastModeIcon: false, | 102 | showFastModeIcon: false, |
| 94 | }); | 103 | }); |
| ... | @@ -107,7 +116,7 @@ describe("buildTraitsTriggerDisplay", () => { | ... | @@ -107,7 +116,7 @@ describe("buildTraitsTriggerDisplay", () => { |
| 107 | { id: "high", label: "High" }, | 116 | { id: "high", label: "High" }, |
| 108 | ], | 117 | ], |
| 109 | }; | 118 | }; |
| 110 | expect(display([unresolved], false)).toEqual({ label: "", showFastModeIcon: false }); | 119 | expect(display([unresolved])).toEqual({ label: "", showFastModeIcon: false }); |
| 111 | }); | 120 | }); |
| 112 | 121 | ||
| 113 | it("still renders the prompt-controlled ultrathink label alongside the bolt", () => { | 122 | it("still renders the prompt-controlled ultrathink label alongside the bolt", () => { |
| ... | @@ -117,7 +126,6 @@ describe("buildTraitsTriggerDisplay", () => { | ... | @@ -117,7 +126,6 @@ describe("buildTraitsTriggerDisplay", () => { |
| 117 | descriptors: [EFFORT, fastModeDescriptor(true)], | 126 | descriptors: [EFFORT, fastModeDescriptor(true)], |
| 118 | primarySelectDescriptorId: "reasoningEffort", | 127 | primarySelectDescriptorId: "reasoningEffort", |
| 119 | ultrathinkPromptControlled: true, | 128 | ultrathinkPromptControlled: true, |
| 120 | fastModeEnabled: true, | ||
| 121 | }), | 129 | }), |
| 122 | ).toEqual({ label: "Ultrathink", showFastModeIcon: true }); | 130 | ).toEqual({ label: "Ultrathink", showFastModeIcon: true }); |
| 123 | }); | 131 | }); |
apps/web/src/components/chat/TraitsPicker.tsx+10-12| ... | @@ -134,8 +134,6 @@ function getSelectedTraits( | ... | @@ -134,8 +134,6 @@ function getSelectedTraits( |
| 134 | : getDescriptorStringValue(primarySelectDescriptor)) ?? null; | 134 | : getDescriptorStringValue(primarySelectDescriptor)) ?? null; |
| 135 | const thinkingEnabled = | 135 | const thinkingEnabled = |
| 136 | typeof thinkingDescriptor?.currentValue === "boolean" ? thinkingDescriptor.currentValue : null; | 136 | typeof thinkingDescriptor?.currentValue === "boolean" ? thinkingDescriptor.currentValue : null; |
| 137 | const fastModeEnabled = | ||
| 138 | typeof fastModeDescriptor?.currentValue === "boolean" ? fastModeDescriptor.currentValue : false; | ||
| 139 | const contextWindow = getDescriptorStringValue(contextWindowDescriptor); | 137 | const contextWindow = getDescriptorStringValue(contextWindowDescriptor); |
| 140 | const selectedAgent = getDescriptorStringValue(agentDescriptor); | 138 | const selectedAgent = getDescriptorStringValue(agentDescriptor); |
| 141 | const selectedAgentLabel = agentDescriptor | 139 | const selectedAgentLabel = agentDescriptor |
| ... | @@ -154,7 +152,6 @@ function getSelectedTraits( | ... | @@ -154,7 +152,6 @@ function getSelectedTraits( |
| 154 | thinkingDescriptor, | 152 | thinkingDescriptor, |
| 155 | effort, | 153 | effort, |
| 156 | thinkingEnabled, | 154 | thinkingEnabled, |
| 157 | fastModeEnabled, | ||
| 158 | contextWindow, | 155 | contextWindow, |
| 159 | ultrathinkPromptControlled, | 156 | ultrathinkPromptControlled, |
| 160 | ultrathinkInBodyText, | 157 | ultrathinkInBodyText, |
| ... | @@ -392,24 +389,26 @@ export function buildTraitsTriggerDisplay(input: { | ... | @@ -392,24 +389,26 @@ export function buildTraitsTriggerDisplay(input: { |
| 392 | descriptors: ReadonlyArray<ProviderOptionDescriptor>; | 389 | descriptors: ReadonlyArray<ProviderOptionDescriptor>; |
| 393 | primarySelectDescriptorId: string | null; | 390 | primarySelectDescriptorId: string | null; |
| 394 | ultrathinkPromptControlled: boolean; | 391 | ultrathinkPromptControlled: boolean; |
| 395 | fastModeEnabled: boolean; | ||
| 396 | }): { label: string; showFastModeIcon: boolean } { | 392 | }): { label: string; showFastModeIcon: boolean } { |
| 397 | let hasFastMode = false; | 393 | let hasFastMode = false; |
| 394 | let fastModeEnabled = false; | ||
| 398 | const labels: Array<string> = []; | 395 | const labels: Array<string> = []; |
| 399 | for (const descriptor of input.descriptors) { | 396 | for (const descriptor of input.descriptors) { |
| 400 | if (descriptor.id === "fastMode" && descriptor.type === "boolean") { | 397 | if (descriptor.id === "fastMode" && descriptor.type === "boolean") { |
| 401 | hasFastMode = true; | 398 | hasFastMode = true; |
| 399 | fastModeEnabled = descriptor.currentValue === true; | ||
| 402 | continue; | 400 | continue; |
| 403 | } | 401 | } |
| 404 | if ( | 402 | if ( |
| 405 | input.provider === "codex" && | 403 | input.provider === "codex" && |
| 406 | descriptor.id === "serviceTier" && | 404 | descriptor.id === "serviceTier" && |
| 407 | descriptor.type === "select" && | 405 | descriptor.type === "select" |
| 408 | input.descriptors.some(({ id }) => id === "reasoningEffort") | ||
| 409 | ) { | 406 | ) { |
| 410 | const currentValue = getProviderOptionCurrentValue(descriptor); | 407 | const currentValue = getProviderOptionCurrentValue(descriptor); |
| 411 | const currentOption = descriptor.options.find((option) => option.id === currentValue); | 408 | const fastTier = descriptor.options.find(({ label }) => label === "Fast"); |
| 412 | if (currentOption?.id === "default" && currentOption.isDefault === true) { | 409 | if (fastTier && (currentValue === "default" || currentValue === fastTier.id)) { |
| 410 | hasFastMode = true; | ||
| 411 | fastModeEnabled = currentValue === fastTier.id; | ||
| 413 | continue; | 412 | continue; |
| 414 | } | 413 | } |
| 415 | } | 414 | } |
| ... | @@ -428,9 +427,9 @@ export function buildTraitsTriggerDisplay(input: { | ... | @@ -428,9 +427,9 @@ export function buildTraitsTriggerDisplay(input: { |
| 428 | // off an empty label list alone would also catch descriptors that resolved to | 427 | // off an empty label list alone would also catch descriptors that resolved to |
| 429 | // no label at all, printing a bogus "Normal" for a model without fast mode. | 428 | // no label at all, printing a bogus "Normal" for a model without fast mode. |
| 430 | if (labels.length === 0 && hasFastMode) { | 429 | if (labels.length === 0 && hasFastMode) { |
| 431 | return { label: input.fastModeEnabled ? "Fast" : "Normal", showFastModeIcon: false }; | 430 | return { label: fastModeEnabled ? "Fast" : "Normal", showFastModeIcon: false }; |
| 432 | } | 431 | } |
| 433 | return { label: labels.join(" · "), showFastModeIcon: input.fastModeEnabled }; | 432 | return { label: labels.join(" · "), showFastModeIcon: fastModeEnabled }; |
| 434 | } | 433 | } |
| 435 | 434 | ||
| 436 | export const TraitsPicker = memo(function TraitsPicker({ | 435 | export const TraitsPicker = memo(function TraitsPicker({ |
| ... | @@ -447,7 +446,7 @@ export const TraitsPicker = memo(function TraitsPicker({ | ... | @@ -447,7 +446,7 @@ export const TraitsPicker = memo(function TraitsPicker({ |
| 447 | ...persistence | 446 | ...persistence |
| 448 | }: TraitsMenuContentProps & TraitsPersistence) { | 447 | }: TraitsMenuContentProps & TraitsPersistence) { |
| 449 | const [isMenuOpen, setIsMenuOpen] = useState(false); | 448 | const [isMenuOpen, setIsMenuOpen] = useState(false); |
| 450 | const { descriptors, primarySelectDescriptor, ultrathinkPromptControlled, fastModeEnabled } = | 449 | const { descriptors, primarySelectDescriptor, ultrathinkPromptControlled } = |
| 451 | getTraitsSectionVisibility({ | 450 | getTraitsSectionVisibility({ |
| 452 | provider, | 451 | provider, |
| 453 | models, | 452 | models, |
| ... | @@ -474,7 +473,6 @@ export const TraitsPicker = memo(function TraitsPicker({ | ... | @@ -474,7 +473,6 @@ export const TraitsPicker = memo(function TraitsPicker({ |
| 474 | descriptors, | 473 | descriptors, |
| 475 | primarySelectDescriptorId: primarySelectDescriptor?.id ?? null, | 474 | primarySelectDescriptorId: primarySelectDescriptor?.id ?? null, |
| 476 | ultrathinkPromptControlled, | 475 | ultrathinkPromptControlled, |
| 477 | fastModeEnabled, | ||
| 478 | }); | 476 | }); |
| 479 | const fastModeIcon = showFastModeIcon ? ( | 477 | const fastModeIcon = showFastModeIcon ? ( |
| 480 | <> | 478 | <> |