| ... | ... | @@ -69,32 +69,108 @@ describe("buildTraitsTriggerDisplay", () => { |
| 69 | 69 | it("omits fast mode from the label entirely when it is off", () => { |
| 70 | 70 | expect(display([EFFORT, fastModeDescriptor(false), CONTEXT_WINDOW])).toEqual({ |
| 71 | 71 | label: "High · 1M", |
| 72 | | speedIcon: null, |
| 73 | 72 | }); |
| 74 | 73 | }); |
| 75 | 74 | |
| 76 | | it("shows the bolt instead of a text label when fast mode is on", () => { |
| 75 | it("pairs fast mode with reasoning before the context window", () => { |
| 77 | 76 | expect(display([EFFORT, fastModeDescriptor(true), CONTEXT_WINDOW])).toEqual({ |
| 78 | | label: "High · 1M", |
| 79 | | speedIcon: "fast", |
| 77 | label: "High Fast · 1M", |
| 78 | }); |
| 79 | expect(display([EFFORT, CONTEXT_WINDOW, fastModeDescriptor(true)])).toEqual({ |
| 80 | label: "High Fast · 1M", |
| 80 | 81 | }); |
| 81 | 82 | }); |
| 82 | 83 | |
| 83 | | it("treats Codex standard and fast service tiers as fast mode states", () => { |
| 84 | | expect(display([EFFORT, serviceTierDescriptor("default")])).toEqual({ |
| 85 | | label: "High", |
| 86 | | speedIcon: null, |
| 87 | | }); |
| 88 | | expect(display([EFFORT, serviceTierDescriptor("priority")])).toEqual({ |
| 89 | | label: "High", |
| 90 | | speedIcon: "fast", |
| 84 | it.each(["reasoningEffort", "reasoning", "effort", "variant", "thinking"])( |
| 85 | "pairs Fast with %s even when context is the primary select", |
| 86 | (id) => { |
| 87 | for (const speed of [fastModeDescriptor(true), serviceTierDescriptor("priority")]) { |
| 88 | expect( |
| 89 | buildTraitsTriggerDisplay({ |
| 90 | provider: CODEX, |
| 91 | descriptors: [ |
| 92 | selectDescriptor("profile", [{ id: "balanced", label: "Balanced" }], "balanced"), |
| 93 | CONTEXT_WINDOW, |
| 94 | { ...EFFORT, id }, |
| 95 | speed, |
| 96 | ], |
| 97 | primarySelectDescriptorId: "profile", |
| 98 | ultrathinkPromptControlled: false, |
| 99 | }), |
| 100 | ).toEqual({ label: "Balanced · 1M · High Fast" }); |
| 101 | } |
| 102 | expect( |
| 103 | buildTraitsTriggerDisplay({ |
| 104 | provider: CODEX, |
| 105 | descriptors: [CONTEXT_WINDOW, { ...EFFORT, id }, serviceTierDescriptor("ultrafast")], |
| 106 | primarySelectDescriptorId: CONTEXT_WINDOW.id, |
| 107 | ultrathinkPromptControlled: false, |
| 108 | }), |
| 109 | ).toEqual({ label: "1M · High Ultrafast" }); |
| 110 | }, |
| 111 | ); |
| 112 | |
| 113 | it("pairs Cursor Fast with reasoning rather than the thinking toggle", () => { |
| 114 | expect( |
| 115 | buildTraitsTriggerDisplay({ |
| 116 | provider: ProviderDriverKind.make("cursor"), |
| 117 | descriptors: [ |
| 118 | { ...EFFORT, id: "reasoning" }, |
| 119 | fastModeDescriptor(true), |
| 120 | { id: "thinking", label: "Thinking", type: "boolean", currentValue: true }, |
| 121 | ], |
| 122 | primarySelectDescriptorId: "reasoning", |
| 123 | ultrathinkPromptControlled: false, |
| 124 | }), |
| 125 | ).toEqual({ label: "High Fast · Thinking On" }); |
| 126 | }); |
| 127 | |
| 128 | it.each([true, false])("keeps boolean thinking %s independent of Fast", (currentValue) => { |
| 129 | const thinking = { |
| 130 | id: "thinking", |
| 131 | label: "Thinking", |
| 132 | type: "boolean" as const, |
| 133 | currentValue, |
| 134 | }; |
| 135 | const label = `Thinking ${currentValue ? "On" : "Off"}`; |
| 136 | expect(display([thinking, fastModeDescriptor(true)])).toEqual({ label: `${label} · Fast` }); |
| 137 | expect(display([thinking, { ...EFFORT, id: "reasoning" }, fastModeDescriptor(true)])).toEqual({ |
| 138 | label: `${label} · High Fast`, |
| 91 | 139 | }); |
| 140 | expect(display([thinking, fastModeDescriptor(false)])).toEqual({ label }); |
| 141 | }); |
| 142 | |
| 143 | it("keeps speed separate when there is no reasoning descriptor", () => { |
| 144 | expect(display([CONTEXT_WINDOW, fastModeDescriptor(true)])).toEqual({ label: "1M · Fast" }); |
| 92 | 145 | }); |
| 93 | 146 | |
| 94 | | it("uses a distinct double bolt for Codex Ultrafast", () => { |
| 147 | it.each(["Low", "Medium", "High", "Extra High", "Max", "Ultra"])( |
| 148 | "preserves %s reasoning with Fast across harnesses", |
| 149 | (label) => { |
| 150 | for (const provider of ["codex", "claudeAgent", "cursor"]) { |
| 151 | expect( |
| 152 | buildTraitsTriggerDisplay({ |
| 153 | provider: ProviderDriverKind.make(provider), |
| 154 | descriptors: [ |
| 155 | { ...EFFORT, options: [{ id: "effort", label }], currentValue: "effort" }, |
| 156 | fastModeDescriptor(true), |
| 157 | ], |
| 158 | primarySelectDescriptorId: EFFORT.id, |
| 159 | ultrathinkPromptControlled: false, |
| 160 | }), |
| 161 | ).toEqual({ label: `${label} Fast` }); |
| 162 | } |
| 163 | }, |
| 164 | ); |
| 165 | |
| 166 | it("treats Codex standard and fast service tiers as fast mode states", () => { |
| 167 | expect(display([EFFORT, serviceTierDescriptor("default")])).toEqual({ label: "High" }); |
| 168 | expect(display([EFFORT, serviceTierDescriptor("priority")])).toEqual({ label: "High Fast" }); |
| 169 | }); |
| 170 | |
| 171 | it("keeps Codex Ultrafast distinct from Fast", () => { |
| 95 | 172 | expect(display([EFFORT, serviceTierDescriptor("ultrafast")])).toEqual({ |
| 96 | | label: "High", |
| 97 | | speedIcon: "ultrafast", |
| 173 | label: "High Ultrafast", |
| 98 | 174 | }); |
| 99 | 175 | }); |
| 100 | 176 | |
| ... | ... | @@ -105,17 +181,11 @@ describe("buildTraitsTriggerDisplay", () => { |
| 105 | 181 | EFFORT, |
| 106 | 182 | { ...descriptor, options: descriptor.options.filter(({ id }) => id !== "priority") }, |
| 107 | 183 | ]), |
| 108 | | ).toEqual({ |
| 109 | | label: "High", |
| 110 | | speedIcon: "ultrafast", |
| 111 | | }); |
| 184 | ).toEqual({ label: "High Ultrafast" }); |
| 112 | 185 | }); |
| 113 | 186 | |
| 114 | 187 | it("keeps other Codex service tiers in the label", () => { |
| 115 | | expect(display([EFFORT, serviceTierDescriptor("flex")])).toEqual({ |
| 116 | | label: "High · Flex", |
| 117 | | speedIcon: null, |
| 118 | | }); |
| 188 | expect(display([EFFORT, serviceTierDescriptor("flex")])).toEqual({ label: "High · Flex" }); |
| 119 | 189 | }); |
| 120 | 190 | |
| 121 | 191 | it("keeps Standard as text for models without speed tiers", () => { |
| ... | ... | @@ -124,32 +194,17 @@ describe("buildTraitsTriggerDisplay", () => { |
| 124 | 194 | ...descriptor, |
| 125 | 195 | options: descriptor.options.filter(({ id }) => id === "default" || id === "flex"), |
| 126 | 196 | }; |
| 127 | | expect(display([EFFORT, nonSpeedDescriptor])).toEqual({ |
| 128 | | label: "High · Standard", |
| 129 | | speedIcon: null, |
| 130 | | }); |
| 131 | | expect(display([nonSpeedDescriptor])).toEqual({ |
| 132 | | label: "Standard", |
| 133 | | speedIcon: null, |
| 134 | | }); |
| 197 | expect(display([EFFORT, nonSpeedDescriptor])).toEqual({ label: "High · Standard" }); |
| 198 | expect(display([nonSpeedDescriptor])).toEqual({ label: "Standard" }); |
| 135 | 199 | }); |
| 136 | 200 | |
| 137 | 201 | it("keeps the Codex service tier readable when it is the only trait", () => { |
| 138 | | expect(display([serviceTierDescriptor("default")])).toEqual({ |
| 139 | | label: "Standard", |
| 140 | | speedIcon: null, |
| 141 | | }); |
| 142 | | expect(display([serviceTierDescriptor("priority")])).toEqual({ |
| 143 | | label: "Fast", |
| 144 | | speedIcon: null, |
| 145 | | }); |
| 202 | expect(display([serviceTierDescriptor("default")])).toEqual({ label: "Standard" }); |
| 203 | expect(display([serviceTierDescriptor("priority")])).toEqual({ label: "Fast" }); |
| 146 | 204 | }); |
| 147 | 205 | |
| 148 | 206 | it("keeps Ultrafast readable when it is the only trait", () => { |
| 149 | | expect(display([serviceTierDescriptor("ultrafast")])).toEqual({ |
| 150 | | label: "Ultrafast", |
| 151 | | speedIcon: null, |
| 152 | | }); |
| 207 | expect(display([serviceTierDescriptor("ultrafast")])).toEqual({ label: "Ultrafast" }); |
| 153 | 208 | }); |
| 154 | 209 | |
| 155 | 210 | it("keeps non-fastMode booleans as text labels", () => { |
| ... | ... | @@ -159,21 +214,16 @@ describe("buildTraitsTriggerDisplay", () => { |
| 159 | 214 | type: "boolean", |
| 160 | 215 | currentValue: true, |
| 161 | 216 | }; |
| 162 | | expect(display([EFFORT, thinking])).toEqual({ |
| 163 | | label: "High · Thinking On", |
| 164 | | speedIcon: null, |
| 165 | | }); |
| 217 | expect(display([EFFORT, thinking])).toEqual({ label: "High · Thinking On" }); |
| 166 | 218 | }); |
| 167 | 219 | |
| 168 | 220 | it("falls back to a text label when fast mode is the only trait", () => { |
| 169 | | expect(display([fastModeDescriptor(true)])).toEqual({ |
| 170 | | label: "Fast", |
| 171 | | speedIcon: null, |
| 172 | | }); |
| 173 | | expect(display([fastModeDescriptor(false)])).toEqual({ |
| 174 | | label: "Normal", |
| 175 | | speedIcon: null, |
| 176 | | }); |
| 221 | expect(display([fastModeDescriptor(true)])).toEqual({ label: "Fast" }); |
| 222 | expect(display([fastModeDescriptor(false)])).toEqual({ label: "Normal" }); |
| 223 | }); |
| 224 | |
| 225 | it("does not add Fast to a model without a speed option", () => { |
| 226 | expect(display([EFFORT, CONTEXT_WINDOW])).toEqual({ label: "High · 1M" }); |
| 177 | 227 | }); |
| 178 | 228 | |
| 179 | 229 | it("stays blank when descriptors resolve to no label and there is no fast mode", () => { |
| ... | ... | @@ -189,10 +239,10 @@ describe("buildTraitsTriggerDisplay", () => { |
| 189 | 239 | { id: "high", label: "High" }, |
| 190 | 240 | ], |
| 191 | 241 | }; |
| 192 | | expect(display([unresolved])).toEqual({ label: "", speedIcon: null }); |
| 242 | expect(display([unresolved])).toEqual({ label: "" }); |
| 193 | 243 | }); |
| 194 | 244 | |
| 195 | | it("still renders the prompt-controlled ultrathink label alongside the bolt", () => { |
| 245 | it("still renders prompt-controlled ultrathink with Fast", () => { |
| 196 | 246 | expect( |
| 197 | 247 | buildTraitsTriggerDisplay({ |
| 198 | 248 | provider: CODEX, |
| ... | ... | @@ -200,7 +250,7 @@ describe("buildTraitsTriggerDisplay", () => { |
| 200 | 250 | primarySelectDescriptorId: "reasoningEffort", |
| 201 | 251 | ultrathinkPromptControlled: true, |
| 202 | 252 | }), |
| 203 | | ).toEqual({ label: "Ultrathink", speedIcon: "fast" }); |
| 253 | ).toEqual({ label: "Ultrathink Fast" }); |
| 204 | 254 | }); |
| 205 | 255 | }); |
| 206 | 256 | |