From 96d48fb0071066afbd4535d53d3bdb28bec58b2e Mon Sep 17 00:00:00 2001 From: Aayam Bansal Date: Tue, 28 Jul 2026 00:19:18 +0800 Subject: [PATCH] Improve ChatGPT Fast mode controls --- backend/cli/src/cli/cmd/models.ts | 4 +-- backend/cli/src/provider/provider.ts | 5 ++-- backend/cli/test/provider/provider.test.ts | 3 ++- frontend/workspace/e2e/model-tier.spec.ts | 25 +++++++++---------- frontend/workspace/e2e/thinking-level.spec.ts | 10 +++++--- frontend/workspace/src/atlas/Composer.tsx | 2 +- .../workspace/src/components/prompt-input.tsx | 16 +++++------- .../src/components/settings/Credentials.tsx | 4 +-- 8 files changed, 33 insertions(+), 36 deletions(-) diff --git a/backend/cli/src/cli/cmd/models.ts b/backend/cli/src/cli/cmd/models.ts index 7f53e525..daa355f6 100644 --- a/backend/cli/src/cli/cmd/models.ts +++ b/backend/cli/src/cli/cmd/models.ts @@ -9,7 +9,7 @@ import { EOL } from "os" const PROVIDER_LABELS: Record = { anthropic: "Anthropic", openai: "OpenAI", - "openai-codex": "OpenAI Codex", + "openai-codex": "OpenAI (ChatGPT subscription)", google: "Google", gemini: "Google Gemini", openrouter: "OpenRouter", @@ -25,7 +25,7 @@ const PROVIDER_LABELS: Record = { * - anything else with a key → BYOK. */ function routingLabel(providerID: string, provider: Provider.Info): string { - if (providerID === "openai-codex") return "Signed in with Codex" + if (providerID === "openai-codex") return "ChatGPT subscription" // Read the EFFECTIVE credential, not just provider.key: a custom loader stores // its key under options.apiKey (e.g. openrouter), and a multi-env provider // (google's GEMINI_API_KEY + GOOGLE_GENERATIVE_AI_API_KEY) leaves provider.key diff --git a/backend/cli/src/provider/provider.ts b/backend/cli/src/provider/provider.ts index 76b289aa..80922437 100644 --- a/backend/cli/src/provider/provider.ts +++ b/backend/cli/src/provider/provider.ts @@ -66,8 +66,7 @@ export namespace Provider { } function codexOAuthModes(modelID: string) { - if (/^gpt-5[.-]4-mini$/.test(modelID)) return undefined - if (!/^gpt-5[.-](?:4|5|6)(?:-(?:sol|terra|luna))?$/.test(modelID)) return undefined + if (!/^gpt-5[.-](?:4(?:-mini)?|5|6(?:-(?:sol|terra|luna))?)$/.test(modelID)) return undefined return { fast: { provider: { @@ -1430,7 +1429,7 @@ export namespace Provider { database["openai-codex"] = { ...baseOpenai, id: "openai-codex", - name: "OpenAI Codex (ChatGPT subscription)", + name: "OpenAI (ChatGPT subscription)", env: [], options: {}, models: codexModels, diff --git a/backend/cli/test/provider/provider.test.ts b/backend/cli/test/provider/provider.test.ts index 31b9f2d1..157823dd 100644 --- a/backend/cli/test/provider/provider.test.ts +++ b/backend/cli/test/provider/provider.test.ts @@ -132,7 +132,8 @@ test("synthesized Codex OAuth models use Codex variants and context instead of p const codex54 = codex.models["gpt-5.4"] expect(Object.keys(codex54.variants ?? {})).toEqual(["low", "medium", "high", "xhigh"]) expect(Object.keys(codex54.modes ?? {})).toEqual(["fast"]) - expect(codex.models["gpt-5.4-mini"].modes).toBeUndefined() + expect(Object.keys(codex.models["gpt-5.4-mini"].modes ?? {})).toEqual(["fast"]) + expect(codex.name).toBe("OpenAI (ChatGPT subscription)") const publicSol = providers.openai?.models["gpt-5.6-sol"] expect(Object.keys(publicSol?.variants ?? {})).toEqual(["none", "low", "medium", "high", "xhigh", "max"]) diff --git a/frontend/workspace/e2e/model-tier.spec.ts b/frontend/workspace/e2e/model-tier.spec.ts index 7874c363..19506d47 100644 --- a/frontend/workspace/e2e/model-tier.spec.ts +++ b/frontend/workspace/e2e/model-tier.spec.ts @@ -1,21 +1,19 @@ import { test, expect } from "./fixtures" import { modelTierCycleSelector, promptSelector } from "./utils" -test("model service mode cycles through supported modes and reaches the prompt request", async ({ - page, - sdk, - gotoSession, -}) => { +test("model Fast mode toggles and reaches the prompt request", async ({ page, sdk, gotoSession }) => { await gotoSession() await page.addStyleTag({ content: `${modelTierCycleSelector} { display: inline-block !important; }`, }) - const button = page.locator(modelTierCycleSelector) - await expect(button).toBeVisible() - await expect(button).toHaveText("standard") - await expect(button).toHaveAttribute("aria-label", /cycle tier: standard/i) + const toggle = page.locator(modelTierCycleSelector) + const input = toggle.locator('[data-slot="switch-input"]') + const control = toggle.locator('[data-slot="switch-control"]') + await expect(toggle).toBeVisible() + await expect(toggle).toHaveText("Fast") + await expect(input).toHaveAttribute("aria-checked", "false") const send = async (tier?: string) => { const request = page.waitForRequest((request) => { @@ -53,12 +51,13 @@ test("model service mode cycles through supported modes and reaches the prompt r ) .toContain(standard) - await button.click() - await expect(button).toHaveText("fast") - await expect(button).toHaveAttribute("aria-label", /cycle tier: fast/i) + await control.click() + await expect(toggle).toHaveText("Fast") + await expect(input).toHaveAttribute("aria-checked", "true") await page.reload() - await expect(button).toHaveText("fast") + await expect(toggle).toHaveText("Fast") + await expect(input).toHaveAttribute("aria-checked", "true") const fast = await send("fast") await expect diff --git a/frontend/workspace/e2e/thinking-level.spec.ts b/frontend/workspace/e2e/thinking-level.spec.ts index 949b9540..fa1dcb54 100644 --- a/frontend/workspace/e2e/thinking-level.spec.ts +++ b/frontend/workspace/e2e/thinking-level.spec.ts @@ -14,7 +14,7 @@ test("thinking effort starts at standard and reaches the prompt request", async if (!exists) return await expect(button).toBeVisible() - await expect(button).toHaveText("standard") + await expect(button).toHaveText("Thinking") await expect(button).toHaveAttribute("aria-label", /thinking effort: standard/i) const send = async (options: { variant?: string; tier?: string } = {}) => { @@ -59,15 +59,17 @@ test("thinking effort starts at standard and reaches the prompt request", async await expect(button).toHaveAttribute("aria-label", /thinking effort: high/i) const tier = page.locator(modelTierCycleSelector) - await tier.click() - await expect(tier).toHaveText("fast") + await tier.locator('[data-slot="switch-control"]').click() + await expect(tier).toHaveText("Fast") + await expect(tier.locator('[data-slot="switch-input"]')).toHaveAttribute("aria-checked", "true") const high = await send({ variant: "high", tier: "fast" }) await expect.poll(output, { timeout: 20_000 }).toContain(high) await page.reload() await expect(button).toHaveText("high") - await expect(tier).toHaveText("fast") + await expect(tier).toHaveText("Fast") + await expect(tier.locator('[data-slot="switch-input"]')).toHaveAttribute("aria-checked", "true") } finally { await sdk.session.delete({ sessionID }).catch(() => undefined) } diff --git a/frontend/workspace/src/atlas/Composer.tsx b/frontend/workspace/src/atlas/Composer.tsx index 43e2da9d..9ca18b3d 100644 --- a/frontend/workspace/src/atlas/Composer.tsx +++ b/frontend/workspace/src/atlas/Composer.tsx @@ -32,7 +32,7 @@ const BYOK_URL = URLS.dashboard const PROVIDER_LABEL: Record = { anthropic: "Anthropic", openai: "OpenAI", - "openai-codex": "OpenAI Codex", + "openai-codex": "OpenAI (ChatGPT subscription)", google: "Google", "google-vertex": "Google Vertex", "github-copilot": "GitHub Copilot", diff --git a/frontend/workspace/src/components/prompt-input.tsx b/frontend/workspace/src/components/prompt-input.tsx index 9478b48c..eecb7a9b 100644 --- a/frontend/workspace/src/components/prompt-input.tsx +++ b/frontend/workspace/src/components/prompt-input.tsx @@ -33,6 +33,7 @@ import { useSync } from "@/context/sync" import { useComments } from "@/context/comments" import { FileIcon } from "@synsci/ui/file-icon" import { Button } from "@synsci/ui/button" +import { Switch as Toggle } from "@synsci/ui/switch" import { Icon } from "@synsci/ui/icon" import { ProviderIcon } from "@synsci/ui/provider-icon" import type { IconName } from "@synsci/ui/icons/provider" @@ -2050,19 +2051,14 @@ export const PromptInput: Component = (props) => { title={language.t("command.tier.cycle")} keybind={command.keybind("tier.cycle")} > - + diff --git a/frontend/workspace/src/components/settings/Credentials.tsx b/frontend/workspace/src/components/settings/Credentials.tsx index df5c0171..d8bb8947 100644 --- a/frontend/workspace/src/components/settings/Credentials.tsx +++ b/frontend/workspace/src/components/settings/Credentials.tsx @@ -462,7 +462,7 @@ export const Credentials: Component = () => {

- {/* Sign in with ChatGPT (Codex OAuth) — an OpenAI plan's credits, no key */} + {/* Sign in with ChatGPT — an OpenAI plan's credits, no key */}
{
Sign in with ChatGPT - Use your ChatGPT Plus / Pro / Business plan (Codex) — no API key needed. + Use your ChatGPT Plus / Pro / Business plan — no API key needed.