From 1acc0aee74aa6a77a33d999febd90962a63234ba Mon Sep 17 00:00:00 2001 From: Roomote Date: Sat, 8 Aug 2026 01:04:27 +0000 Subject: [PATCH 1/7] fix(provider): support Azure OpenAI resource endpoints --- src/api/providers/__tests__/openai.spec.ts | 126 +++++++++++------- src/api/providers/openai.ts | 3 +- .../settings/providers/OpenAICompatible.tsx | 24 +++- .../__tests__/OpenAICompatible.spec.tsx | 44 +++++- webview-ui/src/i18n/locales/en/settings.json | 3 + 5 files changed, 148 insertions(+), 52 deletions(-) diff --git a/src/api/providers/__tests__/openai.spec.ts b/src/api/providers/__tests__/openai.spec.ts index e8146a999a..5fd4a57631 100644 --- a/src/api/providers/__tests__/openai.spec.ts +++ b/src/api/providers/__tests__/openai.spec.ts @@ -3,7 +3,7 @@ import { OpenAiHandler, getOpenAiModels } from "../openai" import { ApiHandlerOptions } from "../../../shared/api" import { Anthropic } from "@anthropic-ai/sdk" -import OpenAI from "openai" +import OpenAI, { AzureOpenAI } from "openai" import { openAiModelInfoSaneDefaults, DEEP_SEEK_DEFAULT_TEMPERATURE } from "@roo-code/types" import { Package } from "../../../shared/package" import { makeApiHandlerOptions } from "../../../test-utils/api" @@ -20,60 +20,63 @@ const mockCreate = vitest.fn() vitest.mock("openai", () => { const mockConstructor = vitest.fn() - return { - __esModule: true, - default: mockConstructor.mockImplementation(function () { - return { - chat: { - completions: { - create: mockCreate.mockImplementation(async (options) => { - if (!options.stream) { - return { - id: "test-completion", - choices: [ - { - message: { role: "assistant", content: "Test response", refusal: null }, - finish_reason: "stop", - index: 0, - }, - ], - usage: { - prompt_tokens: 10, - completion_tokens: 5, - total_tokens: 15, + const mockAzureConstructor = vitest.fn() + function createClient() { + return { + chat: { + completions: { + create: mockCreate.mockImplementation(async (options) => { + if (!options.stream) { + return { + id: "test-completion", + choices: [ + { + message: { role: "assistant", content: "Test response", refusal: null }, + finish_reason: "stop", + index: 0, }, - } + ], + usage: { + prompt_tokens: 10, + completion_tokens: 5, + total_tokens: 15, + }, } + } - return asyncStreamFrom([ - { - choices: [ - { - delta: { content: "Test response" }, - index: 0, - }, - ], - usage: null, - }, - { - choices: [ - { - delta: {}, - index: 0, - }, - ], - usage: { - prompt_tokens: 10, - completion_tokens: 5, - total_tokens: 15, + return asyncStreamFrom([ + { + choices: [ + { + delta: { content: "Test response" }, + index: 0, + }, + ], + usage: null, + }, + { + choices: [ + { + delta: {}, + index: 0, }, + ], + usage: { + prompt_tokens: 10, + completion_tokens: 5, + total_tokens: 15, }, - ]) - }), - }, + }, + ]) + }), }, - } - }), + }, + } + } + return { + __esModule: true, + default: mockConstructor.mockImplementation(createClient), + AzureOpenAI: mockAzureConstructor.mockImplementation(createClient), } }) @@ -126,6 +129,31 @@ describe("OpenAiHandler", () => { timeout: MOCK_TIMEOUT_MS, }) }) + + it.each([ + ["https://resource.openai.azure.com", "https://resource.openai.azure.com/openai"], + ["https://resource.openai.azure.com/", "https://resource.openai.azure.com/openai"], + ["https://resource.openai.azure.com/openai", "https://resource.openai.azure.com/openai"], + ["https://resource.openai.azure.com/openai/", "https://resource.openai.azure.com/openai"], + ])("normalizes Azure OpenAI base URL %s", (openAiBaseUrl, expectedBaseUrl) => { + new OpenAiHandler({ ...mockOptions, openAiBaseUrl }) + + expect(vi.mocked(AzureOpenAI)).toHaveBeenLastCalledWith( + expect.objectContaining({ baseURL: expectedBaseUrl }), + ) + }) + + it("normalizes reverse-proxy URLs when Azure mode is enabled", () => { + new OpenAiHandler({ + ...mockOptions, + openAiBaseUrl: "https://models.example.com/azure/", + openAiUseAzure: true, + }) + + expect(vi.mocked(AzureOpenAI)).toHaveBeenLastCalledWith( + expect.objectContaining({ baseURL: "https://models.example.com/azure/openai" }), + ) + }) }) describe("createMessage", () => { diff --git a/src/api/providers/openai.ts b/src/api/providers/openai.ts index 9545068794..90f453c5d8 100644 --- a/src/api/providers/openai.ts +++ b/src/api/providers/openai.ts @@ -60,8 +60,9 @@ export class OpenAiHandler extends BaseProvider implements SingleCompletionHandl } else if (isAzureOpenAi) { // Azure API shape slightly differs from the core API shape: // https://github.com/openai/openai-node?tab=readme-ov-file#microsoft-azure-openai + const azureBaseURL = `${baseURL.replace(/\/openai\/?$/, "").replace(/\/$/, "")}/openai` this.client = new AzureOpenAI({ - baseURL, + baseURL: azureBaseURL, apiKey, apiVersion: this.options.azureApiVersion || azureOpenAiDefaultApiVersion, defaultHeaders: headers, diff --git a/webview-ui/src/components/settings/providers/OpenAICompatible.tsx b/webview-ui/src/components/settings/providers/OpenAICompatible.tsx index 8b11c128c7..1d636e3e76 100644 --- a/webview-ui/src/components/settings/providers/OpenAICompatible.tsx +++ b/webview-ui/src/components/settings/providers/OpenAICompatible.tsx @@ -42,6 +42,18 @@ export const OpenAICompatible = ({ simplifySettings, }: OpenAICompatibleProps) => { const { t } = useAppTranslation() + const isAzureOpenAi = (() => { + if (apiConfiguration?.openAiUseAzure) { + return true + } + + try { + const host = new URL(apiConfiguration?.openAiBaseUrl || "").host + return host === "azure.com" || host.endsWith(".azure.com") + } catch { + return false + } + })() const [azureApiVersionSelected, setAzureApiVersionSelected] = useState(!!apiConfiguration?.azureApiVersion) @@ -129,7 +141,11 @@ export const OpenAICompatible = ({ value={apiConfiguration?.openAiBaseUrl || ""} type="url" onInput={handleInputChange("openAiBaseUrl")} - placeholder={t("settings:placeholders.baseUrl")} + placeholder={ + isAzureOpenAi + ? t("settings:providers.azureOpenAiBaseUrlPlaceholder") + : t("settings:placeholders.baseUrl") + } className="w-full"> @@ -147,12 +163,18 @@ export const OpenAICompatible = ({ defaultModelId="gpt-4o" models={openAiModels} modelIdKey="openAiModelId" + label={isAzureOpenAi ? t("settings:providers.azureOpenAiDeploymentName") : undefined} serviceName="OpenAI" serviceUrl="https://platform.openai.com" organizationAllowList={organizationAllowList} errorMessage={modelValidationError} simplifySettings={simplifySettings} /> + {isAzureOpenAi && ( +
+ {t("settings:providers.azureOpenAiDeploymentNameDescription")} +
+ )} ({ })) // Mock other components +const { mockModelPicker } = vi.hoisted(() => ({ mockModelPicker: vi.fn() })) + vi.mock("../../ModelPicker", () => ({ - ModelPicker: () =>
Model Picker
, + ModelPicker: (props: any) => { + mockModelPicker(props) + return
Model Picker
+ }, })) vi.mock("../../R1FormatSetting", () => ({ @@ -144,6 +149,43 @@ describe("OpenAICompatible Component - includeMaxTokens checkbox", () => { }) }) + describe("Azure OpenAI guidance", () => { + it.each([ + { openAiBaseUrl: "https://resource.openai.azure.com/" }, + { openAiBaseUrl: "https://models.example.com", openAiUseAzure: true }, + ])("shows Azure-specific endpoint and deployment guidance", (apiConfiguration) => { + render( + , + ) + + expect(screen.getByPlaceholderText("settings:providers.azureOpenAiBaseUrlPlaceholder")).toBeInTheDocument() + expect(mockModelPicker).toHaveBeenLastCalledWith( + expect.objectContaining({ label: "settings:providers.azureOpenAiDeploymentName" }), + ) + expect(screen.getByText("settings:providers.azureOpenAiDeploymentNameDescription")).toBeInTheDocument() + }) + + it("keeps generic OpenAI-compatible guidance for non-Azure endpoints", () => { + render( + , + ) + + expect(screen.getByPlaceholderText("settings:placeholders.baseUrl")).toBeInTheDocument() + expect(mockModelPicker).toHaveBeenLastCalledWith(expect.objectContaining({ label: undefined })) + expect( + screen.queryByText("settings:providers.azureOpenAiDeploymentNameDescription"), + ).not.toBeInTheDocument() + }) + }) + describe("Initial State", () => { it("should show checkbox as checked when includeMaxTokens is true", () => { const apiConfiguration: Partial = { diff --git a/webview-ui/src/i18n/locales/en/settings.json b/webview-ui/src/i18n/locales/en/settings.json index 2aacc322f0..14a7476a75 100644 --- a/webview-ui/src/i18n/locales/en/settings.json +++ b/webview-ui/src/i18n/locales/en/settings.json @@ -575,6 +575,9 @@ "openAiApiKey": "OpenAI API Key", "apiKey": "API Key", "openAiBaseUrl": "Base URL", + "azureOpenAiBaseUrlPlaceholder": "https://.openai.azure.com/openai", + "azureOpenAiDeploymentName": "Azure deployment name", + "azureOpenAiDeploymentNameDescription": "Enter the deployment name from Azure AI Studio, not the underlying model name.", "getOpenAiApiKey": "Get OpenAI API Key", "mistralApiKey": "Mistral API Key", "getMistralApiKey": "Get Mistral / Codestral API Key", From 646693d06025da0eddd6af0e0695ece5ac97e592 Mon Sep 17 00:00:00 2001 From: Roomote Date: Sat, 8 Aug 2026 01:05:50 +0000 Subject: [PATCH 2/7] test(provider): keep Azure constructor mock focused --- src/api/providers/__tests__/openai.spec.ts | 99 +++++++++++----------- 1 file changed, 49 insertions(+), 50 deletions(-) diff --git a/src/api/providers/__tests__/openai.spec.ts b/src/api/providers/__tests__/openai.spec.ts index 5fd4a57631..4844ffedc3 100644 --- a/src/api/providers/__tests__/openai.spec.ts +++ b/src/api/providers/__tests__/openai.spec.ts @@ -21,62 +21,61 @@ const mockCreate = vitest.fn() vitest.mock("openai", () => { const mockConstructor = vitest.fn() const mockAzureConstructor = vitest.fn() - function createClient() { - return { - chat: { - completions: { - create: mockCreate.mockImplementation(async (options) => { - if (!options.stream) { - return { - id: "test-completion", - choices: [ - { - message: { role: "assistant", content: "Test response", refusal: null }, - finish_reason: "stop", - index: 0, + return { + __esModule: true, + default: mockConstructor.mockImplementation(function () { + return { + chat: { + completions: { + create: mockCreate.mockImplementation(async (options) => { + if (!options.stream) { + return { + id: "test-completion", + choices: [ + { + message: { role: "assistant", content: "Test response", refusal: null }, + finish_reason: "stop", + index: 0, + }, + ], + usage: { + prompt_tokens: 10, + completion_tokens: 5, + total_tokens: 15, }, - ], - usage: { - prompt_tokens: 10, - completion_tokens: 5, - total_tokens: 15, - }, + } } - } - return asyncStreamFrom([ - { - choices: [ - { - delta: { content: "Test response" }, - index: 0, - }, - ], - usage: null, - }, - { - choices: [ - { - delta: {}, - index: 0, + return asyncStreamFrom([ + { + choices: [ + { + delta: { content: "Test response" }, + index: 0, + }, + ], + usage: null, + }, + { + choices: [ + { + delta: {}, + index: 0, + }, + ], + usage: { + prompt_tokens: 10, + completion_tokens: 5, + total_tokens: 15, }, - ], - usage: { - prompt_tokens: 10, - completion_tokens: 5, - total_tokens: 15, }, - }, - ]) - }), + ]) + }), + }, }, - }, - } - } - return { - __esModule: true, - default: mockConstructor.mockImplementation(createClient), - AzureOpenAI: mockAzureConstructor.mockImplementation(createClient), + } + }), + AzureOpenAI: mockAzureConstructor, } }) From 3a121b8bbb06ff5443ff4e04cd1a6144dc977407 Mon Sep 17 00:00:00 2001 From: Roomote Date: Sat, 8 Aug 2026 01:26:29 +0000 Subject: [PATCH 3/7] test(settings): snapshot Azure OpenAI guidance --- .../OpenAICompatible.visual.fixture.tsx | 68 +++++++++++++++++++ .../__tests__/OpenAICompatible.visual.tsx | 16 +++++ 2 files changed, 84 insertions(+) create mode 100644 webview-ui/src/components/settings/providers/__tests__/OpenAICompatible.visual.fixture.tsx create mode 100644 webview-ui/src/components/settings/providers/__tests__/OpenAICompatible.visual.tsx diff --git a/webview-ui/src/components/settings/providers/__tests__/OpenAICompatible.visual.fixture.tsx b/webview-ui/src/components/settings/providers/__tests__/OpenAICompatible.visual.fixture.tsx new file mode 100644 index 0000000000..f8af0ed3fd --- /dev/null +++ b/webview-ui/src/components/settings/providers/__tests__/OpenAICompatible.visual.fixture.tsx @@ -0,0 +1,68 @@ +/* v8 ignore file -- Playwright component fixture is covered by the visual test. */ +import React from "react" +import { QueryClient, QueryClientProvider } from "@tanstack/react-query" + +import { type ProviderSettings } from "@roo-code/types" + +import { TranslationContext as AppTranslationContext } from "@/i18n/TranslationContext" +import { TranslationContext as PlaywrightTranslationContext } from "@src/i18n/TranslationContext" +import { TooltipProvider } from "@src/components/ui/tooltip" +import { OpenAICompatible } from "../OpenAICompatible" + +const translations: Record = { + "settings:providers.openAiBaseUrl": "Base URL", + "settings:providers.azureOpenAiBaseUrlPlaceholder": "https://.openai.azure.com/openai", + "settings:providers.apiKey": "API Key", + "settings:placeholders.apiKey": "Enter API key", + "settings:providers.azureOpenAiDeploymentName": "Azure deployment name", + "settings:providers.azureOpenAiDeploymentNameDescription": + "Enter the deployment name from Azure AI Studio, not the underlying model name.", + "settings:modelPicker.simplifiedExplanation": "You can adjust detailed model settings later.", + "settings:modelInfo.enableR1Format": "Enable R1 model parameters", + "settings:modelInfo.enableR1FormatTips": "Enable this only for R1-compatible models.", + "settings:modelInfo.enableStreaming": "Enable streaming", + "settings:includeMaxOutputTokens": "Include max output tokens", + "settings:includeMaxOutputTokensDescription": "Send the configured maximum output token limit.", + "settings:modelInfo.useAzure": "Use Azure", + "settings:modelInfo.azureApiVersion": "Set Azure API version", +} + +const queryClient = new QueryClient({ + defaultOptions: { + queries: { retry: false }, + }, +}) + +const apiConfiguration: ProviderSettings = { + apiProvider: "openai", + openAiBaseUrl: "", + openAiModelId: "my-gpt4o-deployment", + openAiUseAzure: true, +} + +export const OpenAICompatibleAzureFixture = () => ( + translations[key] ?? key, + i18n: null as unknown as typeof import("../../../../i18n/setup").default, + }}> + translations[key] ?? key, + i18n: null as unknown as typeof import("../../../../i18n/setup").default, + }}> + + +
+ {}} + organizationAllowList={{ allowAll: true, providers: {} }} + simplifySettings + /> +
+
+
+
+
+) diff --git a/webview-ui/src/components/settings/providers/__tests__/OpenAICompatible.visual.tsx b/webview-ui/src/components/settings/providers/__tests__/OpenAICompatible.visual.tsx new file mode 100644 index 0000000000..19ffb898de --- /dev/null +++ b/webview-ui/src/components/settings/providers/__tests__/OpenAICompatible.visual.tsx @@ -0,0 +1,16 @@ +import React from "react" + +import { expect, test } from "../../../../../playwright/coverage-fixture" +import { OpenAICompatibleAzureFixture } from "./OpenAICompatible.visual.fixture" + +test("renders Azure OpenAI endpoint and deployment guidance in the VS Code dark theme", async ({ mount, page }) => { + await page.evaluate(() => Object.assign(globalThis, { z: undefined })) + const component = await mount() + + await component.evaluate(async () => { + await document.fonts.ready + await new Promise((resolve) => requestAnimationFrame(() => resolve())) + }) + + await expect(component).toHaveScreenshot("openai-compatible-azure-guidance-dark.png") +}) From dfd281e66b7956766605633680b89600df5c798f Mon Sep 17 00:00:00 2001 From: Roomote Date: Sat, 8 Aug 2026 01:29:10 +0000 Subject: [PATCH 4/7] test(settings): focus Azure guidance snapshot --- .../providers/__tests__/OpenAICompatible.visual.fixture.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/webview-ui/src/components/settings/providers/__tests__/OpenAICompatible.visual.fixture.tsx b/webview-ui/src/components/settings/providers/__tests__/OpenAICompatible.visual.fixture.tsx index f8af0ed3fd..ed81023091 100644 --- a/webview-ui/src/components/settings/providers/__tests__/OpenAICompatible.visual.fixture.tsx +++ b/webview-ui/src/components/settings/providers/__tests__/OpenAICompatible.visual.fixture.tsx @@ -53,7 +53,7 @@ export const OpenAICompatibleAzureFixture = () => ( }}> -
+
{}} From 6cf5a957af5f378508927f54391ddba0959b4e3c Mon Sep 17 00:00:00 2001 From: Roomote Date: Sat, 8 Aug 2026 01:31:33 +0000 Subject: [PATCH 5/7] test(settings): trim Azure guidance snapshot --- .../providers/__tests__/OpenAICompatible.visual.fixture.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/webview-ui/src/components/settings/providers/__tests__/OpenAICompatible.visual.fixture.tsx b/webview-ui/src/components/settings/providers/__tests__/OpenAICompatible.visual.fixture.tsx index ed81023091..1c2d1a5389 100644 --- a/webview-ui/src/components/settings/providers/__tests__/OpenAICompatible.visual.fixture.tsx +++ b/webview-ui/src/components/settings/providers/__tests__/OpenAICompatible.visual.fixture.tsx @@ -53,7 +53,7 @@ export const OpenAICompatibleAzureFixture = () => ( }}> -
+
{}} From d3688f55384178977f70585df1c4b919e4ef4bd0 Mon Sep 17 00:00:00 2001 From: Roomote Date: Sat, 8 Aug 2026 01:34:10 +0000 Subject: [PATCH 6/7] test(settings): add Azure guidance visual baseline --- .../openai-compatible-azure-guidance-dark.png | Bin 0 -> 30063 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 webview-ui/src/components/settings/providers/__tests__/__screenshots__/openai-compatible-azure-guidance-dark.png diff --git a/webview-ui/src/components/settings/providers/__tests__/__screenshots__/openai-compatible-azure-guidance-dark.png b/webview-ui/src/components/settings/providers/__tests__/__screenshots__/openai-compatible-azure-guidance-dark.png new file mode 100644 index 0000000000000000000000000000000000000000..5838212a1dfe62029c8687b62af772a341124181 GIT binary patch literal 30063 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 Date: Sat, 8 Aug 2026 01:39:19 +0000 Subject: [PATCH 7/7] test(settings): explain CT bundle setup --- .../settings/providers/__tests__/OpenAICompatible.visual.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/webview-ui/src/components/settings/providers/__tests__/OpenAICompatible.visual.tsx b/webview-ui/src/components/settings/providers/__tests__/OpenAICompatible.visual.tsx index 19ffb898de..0a522ca0b3 100644 --- a/webview-ui/src/components/settings/providers/__tests__/OpenAICompatible.visual.tsx +++ b/webview-ui/src/components/settings/providers/__tests__/OpenAICompatible.visual.tsx @@ -4,6 +4,7 @@ import { expect, test } from "../../../../../playwright/coverage-fixture" import { OpenAICompatibleAzureFixture } from "./OpenAICompatible.visual.fixture" test("renders Azure OpenAI endpoint and deployment guidance in the VS Code dark theme", async ({ mount, page }) => { + // The full provider bundle leaves a bare Zod reference after CT tree-shaking. await page.evaluate(() => Object.assign(globalThis, { z: undefined })) const component = await mount()