Skip to content

Commit 69e5851

Browse files
committed
feat(webview): add OpenAI Codex speed selector
1 parent 5971caa commit 69e5851

20 files changed

Lines changed: 250 additions & 2 deletions

File tree

webview-ui/src/components/settings/providers/OpenAICodex.tsx

Lines changed: 45 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,23 @@
11
import React from "react"
22

3-
import { type ProviderSettings, openAiCodexDefaultModelId, openAiCodexModels } from "@roo-code/types"
3+
import {
4+
OPEN_AI_CODEX_SERVICE_TIER_KEY,
5+
OpenAiCodexServiceTier,
6+
type ProviderSettings,
7+
openAiCodexDefaultModelId,
8+
openAiCodexModels,
9+
} from "@roo-code/types"
410

511
import { useAppTranslation } from "@src/i18n/TranslationContext"
6-
import { Button } from "@src/components/ui"
12+
import {
13+
Button,
14+
Select,
15+
SelectContent,
16+
SelectItem,
17+
SelectTrigger,
18+
SelectValue,
19+
StandardTooltip,
20+
} from "@src/components/ui"
721
import { vscode } from "@src/utils/vscode"
822

923
import { ModelPicker } from "../ModelPicker"
@@ -66,6 +80,35 @@ export const OpenAICodex: React.FC<OpenAICodexProps> = ({
6680
simplifySettings={simplifySettings}
6781
hidePricing
6882
/>
83+
84+
<div className="flex flex-col gap-1" data-testid="openai-codex-service-tier">
85+
<div className="flex items-center gap-1">
86+
<label className="block font-medium">{t("settings:openAiCodexSpeed.label")}</label>
87+
<StandardTooltip content={t("settings:openAiCodexSpeed.tooltip")}>
88+
<i className="codicon codicon-info text-vscode-descriptionForeground text-xs" />
89+
</StandardTooltip>
90+
</div>
91+
<Select
92+
value={apiConfiguration[OPEN_AI_CODEX_SERVICE_TIER_KEY] ?? OpenAiCodexServiceTier.Default}
93+
onValueChange={(value) =>
94+
setApiConfigurationField(
95+
OPEN_AI_CODEX_SERVICE_TIER_KEY,
96+
value as ProviderSettings[typeof OPEN_AI_CODEX_SERVICE_TIER_KEY],
97+
)
98+
}>
99+
<SelectTrigger className="w-full">
100+
<SelectValue placeholder={t("settings:common.select")} />
101+
</SelectTrigger>
102+
<SelectContent>
103+
<SelectItem value={OpenAiCodexServiceTier.Default}>
104+
{t("settings:openAiCodexSpeed.standard")}
105+
</SelectItem>
106+
<SelectItem value={OpenAiCodexServiceTier.Priority}>
107+
{t("settings:openAiCodexSpeed.fast")}
108+
</SelectItem>
109+
</SelectContent>
110+
</Select>
111+
</div>
69112
</div>
70113
)
71114
}
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
import React from "react"
2+
3+
import {
4+
OPEN_AI_CODEX_SERVICE_TIER_KEY,
5+
OpenAiCodexServiceTier,
6+
providerIdentifiers,
7+
type ProviderSettings,
8+
} from "@roo-code/types"
9+
10+
import { fireEvent, render, screen } from "@/utils/test-utils"
11+
import { vscode } from "@src/utils/vscode"
12+
13+
import { OpenAICodex } from "../OpenAICodex"
14+
15+
vi.mock("@src/i18n/TranslationContext", () => ({
16+
useAppTranslation: () => ({
17+
t: (key: string) =>
18+
({
19+
"settings:openAiCodexSpeed.label": "Speed",
20+
"settings:openAiCodexSpeed.tooltip":
21+
"Fast uses Codex priority processing for about 1.5x speed and consumes more subscription quota.",
22+
"settings:openAiCodexSpeed.standard": "Standard",
23+
"settings:openAiCodexSpeed.fast": "Fast (1.5x speed, increased usage)",
24+
})[key] ?? key,
25+
}),
26+
}))
27+
28+
vi.mock("@src/components/ui", () => ({
29+
Button: ({ children, ...props }: React.ButtonHTMLAttributes<HTMLButtonElement>) => (
30+
<button {...props}>{children}</button>
31+
),
32+
Select: ({ children, value, onValueChange }: any) => (
33+
<select aria-label="Speed" value={value} onChange={(event) => onValueChange(event.target.value)}>
34+
{children}
35+
</select>
36+
),
37+
SelectContent: ({ children }: any) => <>{children}</>,
38+
SelectItem: ({ children, value }: any) => <option value={value}>{children}</option>,
39+
SelectTrigger: ({ children }: any) => <>{children}</>,
40+
SelectValue: () => null,
41+
StandardTooltip: ({ children, content }: any) => <span title={content}>{children}</span>,
42+
}))
43+
44+
vi.mock("../../ModelPicker", () => ({
45+
ModelPicker: () => <div data-testid="model-picker" />,
46+
}))
47+
48+
vi.mock("../OpenAICodexRateLimitDashboard", () => ({
49+
OpenAICodexRateLimitDashboard: () => null,
50+
}))
51+
52+
vi.mock("@src/utils/vscode", () => ({
53+
vscode: { postMessage: vi.fn() },
54+
}))
55+
56+
describe("OpenAICodex speed selector", () => {
57+
const renderSelector = (apiConfiguration: ProviderSettings, setApiConfigurationField = vi.fn()) => {
58+
render(<OpenAICodex apiConfiguration={apiConfiguration} setApiConfigurationField={setApiConfigurationField} />)
59+
return { setApiConfigurationField, selector: screen.getByRole("combobox", { name: "Speed" }) }
60+
}
61+
62+
it("defaults to Standard and clearly explains the Fast quota trade-off", () => {
63+
const { selector } = renderSelector({ apiProvider: providerIdentifiers.openaiCodex })
64+
65+
expect(selector).toHaveValue(OpenAiCodexServiceTier.Default)
66+
expect(screen.getByRole("option", { name: "Standard" })).toBeInTheDocument()
67+
expect(screen.getByRole("option", { name: "Fast (1.5x speed, increased usage)" })).toBeInTheDocument()
68+
expect(
69+
screen.getByTitle(
70+
"Fast uses Codex priority processing for about 1.5x speed and consumes more subscription quota.",
71+
),
72+
).toBeInTheDocument()
73+
})
74+
75+
it("selects Fast from a saved preference and persists changes through the settings callback", () => {
76+
const { selector, setApiConfigurationField } = renderSelector({
77+
apiProvider: providerIdentifiers.openaiCodex,
78+
[OPEN_AI_CODEX_SERVICE_TIER_KEY]: OpenAiCodexServiceTier.Priority,
79+
})
80+
const postMessage = vi.mocked(vscode.postMessage)
81+
82+
expect(selector).toHaveValue(OpenAiCodexServiceTier.Priority)
83+
84+
fireEvent.change(selector, { target: { value: OpenAiCodexServiceTier.Default } })
85+
expect(setApiConfigurationField).toHaveBeenLastCalledWith(
86+
OPEN_AI_CODEX_SERVICE_TIER_KEY,
87+
OpenAiCodexServiceTier.Default,
88+
)
89+
90+
fireEvent.change(selector, { target: { value: OpenAiCodexServiceTier.Priority } })
91+
expect(setApiConfigurationField).toHaveBeenLastCalledWith(
92+
OPEN_AI_CODEX_SERVICE_TIER_KEY,
93+
OpenAiCodexServiceTier.Priority,
94+
)
95+
expect(postMessage).not.toHaveBeenCalled()
96+
})
97+
})

webview-ui/src/i18n/locales/ca/settings.json

Lines changed: 6 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

webview-ui/src/i18n/locales/de/settings.json

Lines changed: 6 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

webview-ui/src/i18n/locales/en/settings.json

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1126,6 +1126,12 @@
11261126
"limitMaxTokensDescription": "Limit the maximum number of tokens in the response",
11271127
"maxOutputTokensLabel": "Max output tokens",
11281128
"maxTokensGenerateDescription": "Maximum tokens to generate in response",
1129+
"openAiCodexSpeed": {
1130+
"label": "Speed",
1131+
"tooltip": "Fast uses Codex priority processing for about 1.5x speed and consumes more subscription quota.",
1132+
"standard": "Standard",
1133+
"fast": "Fast (1.5x speed, increased usage)"
1134+
},
11291135
"serviceTier": {
11301136
"label": "Service tier",
11311137
"tooltip": "For faster processing of API requests, try the priority processing service tier. For lower prices with higher latency, try the flex processing tier.",

webview-ui/src/i18n/locales/es/settings.json

Lines changed: 6 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

webview-ui/src/i18n/locales/fr/settings.json

Lines changed: 6 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

webview-ui/src/i18n/locales/hi/settings.json

Lines changed: 6 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

webview-ui/src/i18n/locales/id/settings.json

Lines changed: 6 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

webview-ui/src/i18n/locales/it/settings.json

Lines changed: 6 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)