From 9bd520edbdc444b0ff392fb05b637380095cfe72 Mon Sep 17 00:00:00 2001 From: Julius Marminge Date: Mon, 9 Mar 2026 09:13:52 -0700 Subject: [PATCH 1/2] Remove service tier setting from Codex flow and contracts - Drop `serviceTier` from orchestration/provider contracts and server dispatch paths - Remove service-tier app setting/UI and related resolver logic - Keep fast badge behavior tied to explicit fast-mode boolean --- .../Layers/ProviderCommandReactor.ts | 17 +++--- apps/server/src/orchestration/decider.ts | 1 - .../src/provider/Layers/CodexAdapter.ts | 1 - apps/web/src/appSettings.test.ts | 20 ++----- apps/web/src/appSettings.ts | 30 +--------- apps/web/src/components/ChatView.tsx | 19 +++--- apps/web/src/routes/_chat.settings.tsx | 60 ++----------------- packages/contracts/src/orchestration.ts | 5 -- packages/contracts/src/provider.ts | 3 - 9 files changed, 26 insertions(+), 130 deletions(-) diff --git a/apps/server/src/orchestration/Layers/ProviderCommandReactor.ts b/apps/server/src/orchestration/Layers/ProviderCommandReactor.ts index 2a72d59027..39f1376431 100644 --- a/apps/server/src/orchestration/Layers/ProviderCommandReactor.ts +++ b/apps/server/src/orchestration/Layers/ProviderCommandReactor.ts @@ -5,7 +5,6 @@ import { type OrchestrationEvent, type ProviderModelOptions, type ProviderKind, - type ProviderServiceTier, type ProviderStartOptions, type OrchestrationSession, ThreadId, @@ -205,7 +204,6 @@ const make = Effect.gen(function* () { readonly provider?: ProviderKind; readonly model?: string; readonly modelOptions?: ProviderModelOptions; - readonly serviceTier?: ProviderServiceTier | null; readonly providerOptions?: ProviderStartOptions; }, ) { @@ -241,7 +239,6 @@ const make = Effect.gen(function* () { : {}), ...(effectiveCwd ? { cwd: effectiveCwd } : {}), ...(desiredModel ? { model: desiredModel } : {}), - ...(options?.serviceTier !== undefined ? { serviceTier: options.serviceTier } : {}), ...(options?.modelOptions !== undefined ? { modelOptions: options.modelOptions } : {}), ...(options?.providerOptions !== undefined ? { providerOptions: options.providerOptions } : {}), ...(input?.resumeCursor !== undefined ? { resumeCursor: input.resumeCursor } : {}), @@ -328,7 +325,6 @@ const make = Effect.gen(function* () { readonly attachments?: ReadonlyArray; readonly provider?: ProviderKind; readonly model?: string; - readonly serviceTier?: ProviderServiceTier | null; readonly modelOptions?: ProviderModelOptions; readonly providerOptions?: ProviderStartOptions; readonly interactionMode?: "default" | "plan"; @@ -344,7 +340,6 @@ const make = Effect.gen(function* () { yield* ensureSessionForThread(input.threadId, input.createdAt, { ...(input.provider !== undefined ? { provider: input.provider } : {}), ...(input.model !== undefined ? { model: input.model } : {}), - ...(input.serviceTier !== undefined ? { serviceTier: input.serviceTier } : {}), ...(input.modelOptions !== undefined ? { modelOptions: input.modelOptions } : {}), ...(input.providerOptions !== undefined ? { providerOptions: input.providerOptions } : {}), }); @@ -365,7 +360,6 @@ const make = Effect.gen(function* () { ...(normalizedInput ? { input: normalizedInput } : {}), ...(normalizedAttachments.length > 0 ? { attachments: normalizedAttachments } : {}), ...(modelForTurn !== undefined ? { model: modelForTurn } : {}), - ...(input.serviceTier !== undefined ? { serviceTier: input.serviceTier } : {}), ...(input.modelOptions !== undefined ? { modelOptions: input.modelOptions } : {}), ...(input.interactionMode !== undefined ? { interactionMode: input.interactionMode } : {}), }); @@ -480,7 +474,6 @@ const make = Effect.gen(function* () { ...(message.attachments !== undefined ? { attachments: message.attachments } : {}), ...(event.payload.provider !== undefined ? { provider: event.payload.provider } : {}), ...(event.payload.model !== undefined ? { model: event.payload.model } : {}), - ...(event.payload.serviceTier !== undefined ? { serviceTier: event.payload.serviceTier } : {}), ...(event.payload.modelOptions !== undefined ? { modelOptions: event.payload.modelOptions } : {}), ...(event.payload.providerOptions !== undefined ? { providerOptions: event.payload.providerOptions } : {}), interactionMode: event.payload.interactionMode, @@ -639,9 +632,13 @@ const make = Effect.gen(function* () { return; } const cachedProviderOptions = threadProviderOptions.get(event.payload.threadId); - yield* ensureSessionForThread(event.payload.threadId, event.occurredAt, { - ...(cachedProviderOptions !== undefined ? { providerOptions: cachedProviderOptions } : {}), - }); + yield* ensureSessionForThread( + event.payload.threadId, + event.occurredAt, + cachedProviderOptions !== undefined + ? { providerOptions: cachedProviderOptions } + : undefined, + ); return; } case "thread.turn-start-requested": diff --git a/apps/server/src/orchestration/decider.ts b/apps/server/src/orchestration/decider.ts index 1c1ca4dd79..2218f88cf5 100644 --- a/apps/server/src/orchestration/decider.ts +++ b/apps/server/src/orchestration/decider.ts @@ -301,7 +301,6 @@ export const decideOrchestrationCommand = Effect.fn("decideOrchestrationCommand" messageId: command.message.messageId, ...(command.provider !== undefined ? { provider: command.provider } : {}), ...(command.model !== undefined ? { model: command.model } : {}), - ...(command.serviceTier !== undefined ? { serviceTier: command.serviceTier } : {}), ...(command.modelOptions !== undefined ? { modelOptions: command.modelOptions } : {}), ...(command.providerOptions !== undefined ? { providerOptions: command.providerOptions } : {}), assistantDeliveryMode: command.assistantDeliveryMode ?? DEFAULT_ASSISTANT_DELIVERY_MODE, diff --git a/apps/server/src/provider/Layers/CodexAdapter.ts b/apps/server/src/provider/Layers/CodexAdapter.ts index 9a6271b792..a31ba2907e 100644 --- a/apps/server/src/provider/Layers/CodexAdapter.ts +++ b/apps/server/src/provider/Layers/CodexAdapter.ts @@ -1354,7 +1354,6 @@ const makeCodexAdapter = (options?: CodexAdapterLiveOptions) => threadId: input.threadId, ...(input.input !== undefined ? { input: input.input } : {}), ...(input.model !== undefined ? { model: input.model } : {}), - ...(input.serviceTier !== undefined ? { serviceTier: input.serviceTier } : {}), ...(input.modelOptions?.codex?.reasoningEffort !== undefined ? { effort: input.modelOptions.codex.reasoningEffort } : {}), diff --git a/apps/web/src/appSettings.test.ts b/apps/web/src/appSettings.test.ts index 5ab5d3c90a..e07e116af7 100644 --- a/apps/web/src/appSettings.test.ts +++ b/apps/web/src/appSettings.test.ts @@ -4,7 +4,6 @@ import { getAppModelOptions, getSlashModelOptions, normalizeCustomModelSlugs, - resolveAppServiceTier, shouldShowFastTierIcon, resolveAppModelSelection, } from "./appSettings"; @@ -85,21 +84,10 @@ describe("getSlashModelOptions", () => { }); }); -describe("resolveAppServiceTier", () => { - it("maps automatic to no override", () => { - expect(resolveAppServiceTier("auto")).toBeNull(); - }); - - it("preserves explicit service tier overrides", () => { - expect(resolveAppServiceTier("fast")).toBe("fast"); - expect(resolveAppServiceTier("flex")).toBe("flex"); - }); -}); - describe("shouldShowFastTierIcon", () => { - it("shows the fast-tier icon only for gpt-5.4 on fast tier", () => { - expect(shouldShowFastTierIcon("gpt-5.4", "fast")).toBe(true); - expect(shouldShowFastTierIcon("gpt-5.4", "auto")).toBe(false); - expect(shouldShowFastTierIcon("gpt-5.3-codex", "fast")).toBe(false); + it("shows the fast-tier icon only for gpt-5.4 when fast mode is enabled", () => { + expect(shouldShowFastTierIcon("gpt-5.4", true)).toBe(true); + expect(shouldShowFastTierIcon("gpt-5.4", false)).toBe(false); + expect(shouldShowFastTierIcon("gpt-5.3-codex", true)).toBe(false); }); }); diff --git a/apps/web/src/appSettings.ts b/apps/web/src/appSettings.ts index e58f7af4a6..53177312cf 100644 --- a/apps/web/src/appSettings.ts +++ b/apps/web/src/appSettings.ts @@ -1,30 +1,11 @@ import { useCallback, useSyncExternalStore } from "react"; import { Option, Schema } from "effect"; -import { type ProviderKind, type ProviderServiceTier } from "@t3tools/contracts"; +import { type ProviderKind } from "@t3tools/contracts"; import { getDefaultModel, getModelOptions, normalizeModelSlug } from "@t3tools/shared/model"; const APP_SETTINGS_STORAGE_KEY = "t3code:app-settings:v1"; const MAX_CUSTOM_MODEL_COUNT = 32; export const MAX_CUSTOM_MODEL_LENGTH = 256; -export const APP_SERVICE_TIER_OPTIONS = [ - { - value: "auto", - label: "Automatic", - description: "Use Codex defaults without forcing a service tier.", - }, - { - value: "fast", - label: "Fast", - description: "Request the fast service tier when the model supports it.", - }, - { - value: "flex", - label: "Flex", - description: "Request the flex service tier when the model supports it.", - }, -] as const; -export type AppServiceTier = (typeof APP_SERVICE_TIER_OPTIONS)[number]["value"]; -const AppServiceTierSchema = Schema.Literals(["auto", "fast", "flex"]); const MODELS_WITH_FAST_SUPPORT = new Set(["gpt-5.4"]); const BUILT_IN_MODEL_SLUGS_BY_PROVIDER: Record> = { codex: new Set(getModelOptions("codex").map((option) => option.slug)), @@ -41,7 +22,6 @@ const AppSettingsSchema = Schema.Struct({ enableAssistantStreaming: Schema.Boolean.pipe( Schema.withConstructorDefault(() => Option.some(false)), ), - codexServiceTier: AppServiceTierSchema.pipe(Schema.withConstructorDefault(() => Option.some("auto"))), customCodexModels: Schema.Array(Schema.String).pipe( Schema.withConstructorDefault(() => Option.some([])), ), @@ -53,17 +33,13 @@ export interface AppModelOption { isCustom: boolean; } -export function resolveAppServiceTier(serviceTier: AppServiceTier): ProviderServiceTier | null { - return serviceTier === "auto" ? null : serviceTier; -} - export function shouldShowFastTierIcon( model: string | null | undefined, - serviceTier: AppServiceTier, + fastModeEnabled: boolean, ): boolean { const normalizedModel = normalizeModelSlug(model); return ( - resolveAppServiceTier(serviceTier) === "fast" && + fastModeEnabled && normalizedModel !== null && MODELS_WITH_FAST_SUPPORT.has(normalizedModel) ); diff --git a/apps/web/src/components/ChatView.tsx b/apps/web/src/components/ChatView.tsx index 51b300ba8e..25cb57e889 100644 --- a/apps/web/src/components/ChatView.tsx +++ b/apps/web/src/components/ChatView.tsx @@ -205,9 +205,7 @@ import { readNativeApi } from "~/nativeApi"; import { getAppModelOptions, resolveAppModelSelection, - resolveAppServiceTier, shouldShowFastTierIcon, - type AppServiceTier, useAppSettings, } from "../appSettings"; import { @@ -785,8 +783,6 @@ export default function ChatView({ threadId }: ChatViewProps) { activeThread.messages.length > 0 || activeThread.session !== null), ); - const selectedServiceTierSetting = settings.codexServiceTier; - const selectedServiceTier = resolveAppServiceTier(selectedServiceTierSetting); const lockedProvider: ProviderKind | null = hasThreadStarted ? (sessionProvider ?? selectedProviderByThreadId ?? null) : null; @@ -1255,9 +1251,9 @@ export default function ChatView({ threadId }: ChatViewProps) { label: name, description: `${providerLabel} · ${slug}`, showFastBadge: - provider === "codex" && shouldShowFastTierIcon(slug, selectedServiceTierSetting), + provider === "codex" && shouldShowFastTierIcon(slug, selectedCodexFastModeEnabled), })); - }, [composerTrigger, searchableModelOptions, selectedServiceTierSetting, workspaceEntries]); + }, [composerTrigger, searchableModelOptions, selectedCodexFastModeEnabled, workspaceEntries]); const composerMenuOpen = Boolean(composerTrigger); const activeComposerMenuItem = useMemo( () => @@ -2664,7 +2660,6 @@ export default function ChatView({ threadId }: ChatViewProps) { attachments: turnAttachments, }, model: selectedModel || undefined, - serviceTier: selectedServiceTier, ...(selectedModelOptionsForDispatch ? { modelOptions: selectedModelOptionsForDispatch } : {}), @@ -3699,7 +3694,7 @@ export default function ChatView({ threadId }: ChatViewProps) { model={selectedModelForPickerWithCustomFallback} lockedProvider={lockedProvider} modelOptionsByProvider={modelOptionsByProvider} - serviceTierSetting={selectedServiceTierSetting} + fastModeEnabled={selectedCodexFastModeEnabled} onProviderModelChange={onProviderModelSelect} /> @@ -5542,7 +5537,7 @@ const ProviderModelPicker = memo(function ProviderModelPicker(props: { model: ModelSlug; lockedProvider: ProviderKind | null; modelOptionsByProvider: Record>; - serviceTierSetting: AppServiceTier; + fastModeEnabled: boolean; disabled?: boolean; onProviderModelChange: (provider: ProviderKind, model: ModelSlug) => void; }) { @@ -5572,10 +5567,10 @@ const ProviderModelPicker = memo(function ProviderModelPicker(props: { disabled={props.disabled} /> } - > + >