From 2f0cb2f54be5742d6fc7e9b85ba39808ac22ad93 Mon Sep 17 00:00:00 2001 From: "paseo-bot[bot]" <266920839+paseo-bot[bot]@users.noreply.github.com> Date: Mon, 5 Oct 2026 21:10:24 +0100 Subject: [PATCH] Show the Codex speed bolt in yellow while Fast or Ultrafast is selected (#6152) * fix(app): fill the speed icon for accelerated tiers * fix(app): highlight the Codex speed bolt when Fast or Ultrafast is selected Codex speed moved from the Fast toggle to a Speed selector, and the composer only colored toggle features, so the bolt stayed muted for every speed. A select feature is now active when its selected option is not the default, and the Codex speed takes the same yellow highlight as the Fast toggle, on the desktop toolbar and in the compact sheet. Closes #5939 Co-authored-by: Nurshot <85260051+Nurshot@users.noreply.github.com> * test(app): assert the Codex speed bolt is yellow on desktop and compact --------- Co-authored-by: Nurshot <85260051+Nurshot@users.noreply.github.com> Co-authored-by: paseo-bot[bot] <266920839+paseo-bot[bot]@users.noreply.github.com> --- packages/app/e2e/browser/codex-speed.spec.ts | 17 +++++++++++++ packages/app/src/agent-controls/policy.ts | 1 + .../app/src/composer/agent-controls/index.tsx | 24 ++++++++++++------- .../src/composer/agent-controls/utils.test.ts | 24 +++++++++++++++++++ .../app/src/composer/agent-controls/utils.ts | 13 +++++++++- 5 files changed, 70 insertions(+), 9 deletions(-) diff --git a/packages/app/e2e/browser/codex-speed.spec.ts b/packages/app/e2e/browser/codex-speed.spec.ts index 654f15207d..ca8c3d8991 100644 --- a/packages/app/e2e/browser/codex-speed.spec.ts +++ b/packages/app/e2e/browser/codex-speed.spec.ts @@ -26,6 +26,10 @@ test.use({ }, }); +// Rendered light-theme colors: palette yellow 400 for Fast and Ultrafast, muted foreground for Normal. +const ACTIVE_SPEED_COLOR = "rgb(251, 191, 36)"; +const NORMAL_SPEED_COLOR = "rgb(113, 113, 122)"; + async function openSpeedSelector(page: Page): Promise { const speed = page.getByRole("button", { name: /^(Select speed|Speed: .+)$/ }); const features = page.getByRole("button", { name: "Open agent features", exact: true }); @@ -51,6 +55,13 @@ async function selectSpeed(page: Page, label: string): Promise { else await expect(sheetTrigger).toContainText(label); } +async function expectSpeedIconColor(page: Page, color: string): Promise { + const trigger = page + .getByRole("button", { name: /^(Speed: .+|Select speed)$/ }) + .filter({ visible: true }); + await expect(trigger.locator("svg").first()).toHaveCSS("stroke", color); +} + async function expectSpeedChoices(page: Page, choices: string[]): Promise { for (const choice of ["Normal", "Fast", "Ultrafast"]) { const option = page.getByText(choice, { exact: true }).last(); @@ -100,15 +111,21 @@ for (const viewport of [ await page.screenshot({ path: testInfo.outputPath("desktop-normal-trigger.png") }); } await openSpeedSelector(page); + await selectSpeed(page, "Fast"); + await expectSpeedIconColor(page, ACTIVE_SPEED_COLOR); + await page.screenshot({ path: testInfo.outputPath(`${viewport.name}-fast-selected.png`) }); + await openSpeedSelector(page); await expectSpeedChoices(page, ["Normal", "Fast", "Ultrafast"]); await page.screenshot({ path: testInfo.outputPath(`${viewport.name}-speed-options.png`) }); await selectSpeed(page, "Ultrafast"); + await expectSpeedIconColor(page, ACTIVE_SPEED_COLOR); await openSpeedSelector(page); await expectSpeedChoices(page, ["Normal", "Fast", "Ultrafast"]); await page.screenshot({ path: testInfo.outputPath(`${viewport.name}-ultrafast-selected.png`), }); await selectSpeed(page, "Normal"); + await expectSpeedIconColor(page, NORMAL_SPEED_COLOR); if (viewport.name === "desktop") { await switchAgentModel(agent.id, "gpt-6-sol"); await openSpeedSelector(page); diff --git a/packages/app/src/agent-controls/policy.ts b/packages/app/src/agent-controls/policy.ts index 827dfadf57..89a4a86daa 100644 --- a/packages/app/src/agent-controls/policy.ts +++ b/packages/app/src/agent-controls/policy.ts @@ -2,6 +2,7 @@ import type { AgentMode } from "@getpaseo/protocol/agent-types"; export const PLAN_MODE_FEATURE_ID = "plan_mode"; export const FAST_MODE_FEATURE_ID = "fast_mode"; +export const SPEED_FEATURE_ID = "service_tier"; export function isPlanningAgentMode(mode: Pick): boolean { return mode.colorTier === "planning" || mode.id === "plan" || mode.id.endsWith("#plan"); diff --git a/packages/app/src/composer/agent-controls/index.tsx b/packages/app/src/composer/agent-controls/index.tsx index d5f09dc77f..72795289cf 100644 --- a/packages/app/src/composer/agent-controls/index.tsx +++ b/packages/app/src/composer/agent-controls/index.tsx @@ -55,6 +55,7 @@ import type { import type { AgentProviderDefinition } from "@getpaseo/protocol/provider-manifest"; import { getFeatureHighlightColor, + isFeatureActive, getFeatureTooltip, getAgentControlHintKey, resolveAgentModelSelection, @@ -211,8 +212,7 @@ function getModeProviderDefinitions(modeControl: AgentModeControlValue | null) { } function getFeatureIconColor( - featureId: string, - enabled: boolean, + feature: AgentFeature, palette: { blue: { 400: string }; green: { 400: string }; @@ -220,11 +220,11 @@ function getFeatureIconColor( }, foregroundMuted: string, ): string { - if (!enabled) { + if (!isFeatureActive(feature)) { return foregroundMuted; } - switch (getFeatureHighlightColor(featureId)) { + switch (getFeatureHighlightColor(feature.id)) { case "blue": return palette.blue[400]; case "green": @@ -1335,8 +1335,7 @@ function DesktopFeatureItem({ { it("maps feature highlight colors by feature id", () => { expect(getFeatureHighlightColor("fast_mode")).toBe("yellow"); + expect(getFeatureHighlightColor("service_tier")).toBe("yellow"); expect(getFeatureHighlightColor("plan_mode")).toBe("blue"); expect(getFeatureHighlightColor("other")).toBe("default"); }); + + it("treats a select feature as active when a non-default option is selected", () => { + const speed = { + type: "select" as const, + id: "service_tier", + label: "Speed", + options: [ + { id: "default", label: "Normal", isDefault: true }, + { id: "fast", label: "Fast" }, + ], + }; + expect(isFeatureActive({ ...speed, value: "default" })).toBe(false); + expect(isFeatureActive({ ...speed, value: "fast" })).toBe(true); + expect( + isFeatureActive({ + type: "toggle", + id: "fast_mode", + label: "Fast", + value: true, + }), + ).toBe(true); + }); }); describe("normalizeModelId", () => { diff --git a/packages/app/src/composer/agent-controls/utils.ts b/packages/app/src/composer/agent-controls/utils.ts index 631b55753e..c0b1da7c47 100644 --- a/packages/app/src/composer/agent-controls/utils.ts +++ b/packages/app/src/composer/agent-controls/utils.ts @@ -1,7 +1,11 @@ import type { AgentFeature, AgentModelDefinition } from "@getpaseo/protocol/agent-types"; import { i18n } from "@/i18n/i18next"; import { formatThinkingOptionLabel } from "@/agent-controls/labels"; -import { FAST_MODE_FEATURE_ID, PLAN_MODE_FEATURE_ID } from "@/agent-controls/policy"; +import { + FAST_MODE_FEATURE_ID, + PLAN_MODE_FEATURE_ID, + SPEED_FEATURE_ID, +} from "@/agent-controls/policy"; export type ExplainedAgentControl = "mode" | "model" | "thinking"; export type FeatureHighlightColor = "blue" | "default" | "green" | "yellow"; @@ -35,9 +39,16 @@ export function getFeatureTooltip(feature: Pick option.id === feature.value); + return selectedOption !== undefined && !selectedOption.isDefault; +} + export function getFeatureHighlightColor(featureId: string): FeatureHighlightColor { switch (featureId) { case FAST_MODE_FEATURE_ID: + case SPEED_FEATURE_ID: return "yellow"; case "auto_accept": return "green";