From 926c23c12737cff8029e63661261d48fdb02d1d5 Mon Sep 17 00:00:00 2001 From: Hannes Rudolph Date: Thu, 5 Feb 2026 15:29:11 -0700 Subject: [PATCH] feat(azure): add model metadata, model picker, rename to Azure AI Foundry - Add static model metadata for 29 Azure models (from models.dev) with Roo-specific flags (reasoning, tools, verbosity) matching openAiNativeModels - Add model picker dropdown to Azure provider settings for model capability detection (context window, max tokens, pricing) - Rename provider label from 'Azure OpenAI' to 'Azure AI Foundry' across all 18 locales - Make API key optional (supports Azure managed identity / Entra ID) - Update default API version from 2024-08-01-preview to 2025-04-01-preview - Fix maxOutputTokens validation (filter invalid values <= 0) - Handler separates deployment name (API calls) from model ID (capability lookup) with azureDefaultModelInfo (gpt-4o) fallback - Remove unhelpful 'Get Azure AI Foundry Access' button - Prevent stale model IDs from other providers carrying over - Suppress validation errors on fresh provider selection --- packages/types/src/provider-settings.ts | 5 +- packages/types/src/providers/azure.ts | 403 ++++++++++++++++++ packages/types/src/providers/index.ts | 4 + packages/types/src/providers/openai.ts | 5 +- src/api/providers/__tests__/azure.spec.ts | 2 +- src/api/providers/azure.ts | 31 +- src/shared/checkExistApiConfig.ts | 8 +- .../src/components/settings/constants.ts | 4 +- .../components/settings/providers/Azure.tsx | 8 - .../settings/utils/providerModelConfig.ts | 6 + .../components/ui/hooks/useSelectedModel.ts | 12 +- webview-ui/src/i18n/locales/ca/settings.json | 4 +- webview-ui/src/i18n/locales/de/settings.json | 4 +- webview-ui/src/i18n/locales/en/settings.json | 4 +- webview-ui/src/i18n/locales/es/settings.json | 4 +- webview-ui/src/i18n/locales/fr/settings.json | 4 +- webview-ui/src/i18n/locales/hi/settings.json | 4 +- webview-ui/src/i18n/locales/id/settings.json | 4 +- webview-ui/src/i18n/locales/it/settings.json | 4 +- webview-ui/src/i18n/locales/ja/settings.json | 4 +- webview-ui/src/i18n/locales/ko/settings.json | 4 +- webview-ui/src/i18n/locales/nl/settings.json | 4 +- webview-ui/src/i18n/locales/pl/settings.json | 4 +- .../src/i18n/locales/pt-BR/settings.json | 4 +- webview-ui/src/i18n/locales/ru/settings.json | 4 +- webview-ui/src/i18n/locales/tr/settings.json | 4 +- webview-ui/src/i18n/locales/vi/settings.json | 4 +- .../src/i18n/locales/zh-CN/settings.json | 4 +- .../src/i18n/locales/zh-TW/settings.json | 4 +- webview-ui/src/utils/validate.ts | 10 +- 30 files changed, 501 insertions(+), 69 deletions(-) create mode 100644 packages/types/src/providers/azure.ts diff --git a/packages/types/src/provider-settings.ts b/packages/types/src/provider-settings.ts index f8d0a5556b..935e84d360 100644 --- a/packages/types/src/provider-settings.ts +++ b/packages/types/src/provider-settings.ts @@ -637,8 +637,9 @@ export const MODELS_BY_PROVIDER: Record< }, azure: { id: "azure", - label: "Azure OpenAI", - models: [], // Azure uses deployment names configured by the user + label: "Azure AI Foundry", + // Azure uses deployment names configured by the user (not a fixed upstream model ID list) + models: [], }, bedrock: { id: "bedrock", diff --git a/packages/types/src/providers/azure.ts b/packages/types/src/providers/azure.ts new file mode 100644 index 0000000000..8ba3480070 --- /dev/null +++ b/packages/types/src/providers/azure.ts @@ -0,0 +1,403 @@ +import type { ModelInfo } from "../model.js" + +/** + * Azure AI Foundry model metadata. + * + * NOTE: + * - Azure AI Foundry uses *deployment names* at runtime, but Roo still needs underlying model + * capabilities (maxTokens/contextWindow/etc.) for validation and parameter shaping. + * - This list is derived from https://models.dev/api.json (provider: "azure") and intentionally + * restricted to OpenAI/Azure OpenAI-style IDs (gpt-*, o*, codex-*). + */ +export const azureModels = { + "codex-mini": { + maxTokens: 100_000, + contextWindow: 200_000, + supportsImages: false, + supportsPromptCache: true, + inputPrice: 1.5, + outputPrice: 6, + cacheReadsPrice: 0.375, + supportsTemperature: false, + description: + "Codex Mini: Cloud-based software engineering agent powered by codex-1, a version of o3 optimized for coding tasks", + }, + "gpt-4": { + maxTokens: 8_192, + contextWindow: 8_192, + supportsImages: false, + supportsPromptCache: false, + inputPrice: 60, + outputPrice: 120, + supportsTemperature: true, + description: "GPT-4", + }, + "gpt-4-32k": { + maxTokens: 32_768, + contextWindow: 32_768, + supportsImages: false, + supportsPromptCache: false, + inputPrice: 60, + outputPrice: 120, + supportsTemperature: true, + description: "GPT-4 32K", + }, + "gpt-4-turbo": { + maxTokens: 4_096, + contextWindow: 128_000, + supportsImages: true, + supportsPromptCache: false, + inputPrice: 10, + outputPrice: 30, + supportsTemperature: true, + description: "GPT-4 Turbo", + }, + "gpt-4-turbo-vision": { + maxTokens: 4_096, + contextWindow: 128_000, + supportsImages: true, + supportsPromptCache: false, + inputPrice: 10, + outputPrice: 30, + supportsTemperature: true, + description: "GPT-4 Turbo Vision", + }, + "gpt-4.1": { + maxTokens: 32_768, + contextWindow: 1_047_576, + supportsImages: true, + supportsPromptCache: true, + inputPrice: 2, + outputPrice: 8, + cacheReadsPrice: 0.5, + supportsTemperature: true, + description: "GPT-4.1", + }, + "gpt-4.1-mini": { + maxTokens: 32_768, + contextWindow: 1_047_576, + supportsImages: true, + supportsPromptCache: true, + inputPrice: 0.4, + outputPrice: 1.6, + cacheReadsPrice: 0.1, + supportsTemperature: true, + description: "GPT-4.1 mini", + }, + "gpt-4.1-nano": { + maxTokens: 32_768, + contextWindow: 1_047_576, + supportsImages: true, + supportsPromptCache: true, + inputPrice: 0.1, + outputPrice: 0.4, + cacheReadsPrice: 0.03, + supportsTemperature: true, + description: "GPT-4.1 nano", + }, + "gpt-4o": { + maxTokens: 16_384, + contextWindow: 128_000, + supportsImages: true, + supportsPromptCache: true, + inputPrice: 2.5, + outputPrice: 10, + cacheReadsPrice: 1.25, + supportsTemperature: true, + description: "GPT-4o", + }, + "gpt-4o-mini": { + maxTokens: 16_384, + contextWindow: 128_000, + supportsImages: true, + supportsPromptCache: true, + inputPrice: 0.15, + outputPrice: 0.6, + cacheReadsPrice: 0.08, + supportsTemperature: true, + description: "GPT-4o mini", + }, + "gpt-5": { + maxTokens: 128_000, + contextWindow: 272_000, + includedTools: ["apply_patch"], + excludedTools: ["apply_diff", "write_to_file"], + supportsImages: true, + supportsPromptCache: true, + supportsReasoningEffort: ["minimal", "low", "medium", "high"], + reasoningEffort: "medium", + inputPrice: 1.25, + outputPrice: 10, + cacheReadsPrice: 0.13, + supportsVerbosity: true, + supportsTemperature: false, + description: "GPT-5: The best model for coding and agentic tasks across domains", + }, + "gpt-5-codex": { + maxTokens: 128_000, + contextWindow: 400_000, + includedTools: ["apply_patch"], + excludedTools: ["apply_diff", "write_to_file"], + supportsImages: true, + supportsPromptCache: true, + supportsReasoningEffort: ["low", "medium", "high"], + reasoningEffort: "medium", + inputPrice: 1.25, + outputPrice: 10, + cacheReadsPrice: 0.13, + supportsTemperature: false, + description: "GPT-5-Codex: A version of GPT-5 optimized for agentic coding in Codex", + }, + "gpt-5-mini": { + maxTokens: 128_000, + contextWindow: 272_000, + includedTools: ["apply_patch"], + excludedTools: ["apply_diff", "write_to_file"], + supportsImages: true, + supportsPromptCache: true, + supportsReasoningEffort: ["minimal", "low", "medium", "high"], + reasoningEffort: "medium", + inputPrice: 0.25, + outputPrice: 2, + cacheReadsPrice: 0.03, + supportsVerbosity: true, + supportsTemperature: false, + description: "GPT-5 Mini: A faster, more cost-efficient version of GPT-5 for well-defined tasks", + }, + "gpt-5-nano": { + maxTokens: 128_000, + contextWindow: 272_000, + includedTools: ["apply_patch"], + excludedTools: ["apply_diff", "write_to_file"], + supportsImages: true, + supportsPromptCache: true, + supportsReasoningEffort: ["minimal", "low", "medium", "high"], + reasoningEffort: "medium", + inputPrice: 0.05, + outputPrice: 0.4, + cacheReadsPrice: 0.01, + supportsVerbosity: true, + supportsTemperature: false, + description: "GPT-5 Nano: Fastest, most cost-efficient version of GPT-5", + }, + "gpt-5-pro": { + maxTokens: 272_000, + contextWindow: 400_000, + includedTools: ["apply_patch"], + excludedTools: ["apply_diff", "write_to_file"], + supportsImages: true, + supportsPromptCache: false, + supportsReasoningEffort: ["minimal", "low", "medium", "high"], + reasoningEffort: "medium", + inputPrice: 15, + outputPrice: 120, + supportsVerbosity: true, + supportsTemperature: false, + description: "GPT-5 Pro", + }, + "gpt-5.1": { + maxTokens: 128_000, + contextWindow: 272_000, + includedTools: ["apply_patch"], + excludedTools: ["apply_diff", "write_to_file"], + supportsImages: true, + supportsPromptCache: true, + promptCacheRetention: "24h", + supportsReasoningEffort: ["none", "low", "medium", "high"], + reasoningEffort: "medium", + inputPrice: 1.25, + outputPrice: 10, + cacheReadsPrice: 0.125, + supportsVerbosity: true, + supportsTemperature: false, + description: "GPT-5.1: The best model for coding and agentic tasks across domains", + }, + "gpt-5.1-chat": { + maxTokens: 16_384, + contextWindow: 128_000, + includedTools: ["apply_patch"], + excludedTools: ["apply_diff", "write_to_file"], + supportsImages: true, + supportsPromptCache: true, + promptCacheRetention: "24h", + inputPrice: 1.25, + outputPrice: 10, + cacheReadsPrice: 0.125, + supportsTemperature: false, + description: "GPT-5.1 Chat: Optimized for conversational AI and chat use cases", + }, + "gpt-5.1-codex": { + maxTokens: 128_000, + contextWindow: 400_000, + includedTools: ["apply_patch"], + excludedTools: ["apply_diff", "write_to_file"], + supportsImages: true, + supportsPromptCache: true, + promptCacheRetention: "24h", + supportsReasoningEffort: ["low", "medium", "high"], + reasoningEffort: "medium", + inputPrice: 1.25, + outputPrice: 10, + cacheReadsPrice: 0.125, + supportsTemperature: false, + description: "GPT-5.1 Codex: A version of GPT-5.1 optimized for agentic coding in Codex", + }, + "gpt-5.1-codex-max": { + maxTokens: 128_000, + contextWindow: 400_000, + includedTools: ["apply_patch"], + excludedTools: ["apply_diff", "write_to_file"], + supportsImages: true, + supportsPromptCache: true, + promptCacheRetention: "24h", + supportsReasoningEffort: ["low", "medium", "high", "xhigh"], + reasoningEffort: "medium", + inputPrice: 1.25, + outputPrice: 10, + cacheReadsPrice: 0.125, + supportsTemperature: false, + description: + "GPT-5.1 Codex Max: Our most intelligent coding model optimized for long-horizon, agentic coding tasks", + }, + "gpt-5.1-codex-mini": { + maxTokens: 128_000, + contextWindow: 400_000, + includedTools: ["apply_patch"], + excludedTools: ["apply_diff", "write_to_file"], + supportsImages: true, + supportsPromptCache: true, + promptCacheRetention: "24h", + supportsReasoningEffort: ["low", "medium", "high"], + reasoningEffort: "medium", + inputPrice: 0.25, + outputPrice: 2, + cacheReadsPrice: 0.025, + supportsTemperature: false, + description: "GPT-5.1 Codex mini: A version of GPT-5.1 optimized for agentic coding in Codex", + }, + "gpt-5.2": { + maxTokens: 128_000, + contextWindow: 400_000, + includedTools: ["apply_patch"], + excludedTools: ["apply_diff", "write_to_file"], + supportsImages: true, + supportsPromptCache: true, + promptCacheRetention: "24h", + supportsReasoningEffort: ["none", "low", "medium", "high", "xhigh"], + reasoningEffort: "medium", + inputPrice: 1.75, + outputPrice: 14, + cacheReadsPrice: 0.125, + supportsVerbosity: true, + supportsTemperature: false, + description: "GPT-5.2: Our flagship model for coding and agentic tasks across industries", + }, + "gpt-5.2-chat": { + maxTokens: 16_384, + contextWindow: 128_000, + includedTools: ["apply_patch"], + excludedTools: ["apply_diff", "write_to_file"], + supportsImages: true, + supportsPromptCache: true, + inputPrice: 1.75, + outputPrice: 14, + cacheReadsPrice: 0.175, + supportsTemperature: false, + description: "GPT-5.2 Chat: Optimized for conversational AI and chat use cases", + }, + "gpt-5.2-codex": { + maxTokens: 128_000, + contextWindow: 400_000, + includedTools: ["apply_patch"], + excludedTools: ["apply_diff", "write_to_file"], + supportsImages: true, + supportsPromptCache: true, + promptCacheRetention: "24h", + supportsReasoningEffort: ["low", "medium", "high", "xhigh"], + reasoningEffort: "medium", + inputPrice: 1.75, + outputPrice: 14, + cacheReadsPrice: 0.175, + supportsTemperature: false, + description: + "GPT-5.2 Codex: Our most intelligent coding model optimized for long-horizon, agentic coding tasks", + }, + o1: { + maxTokens: 100_000, + contextWindow: 200_000, + supportsImages: true, + supportsPromptCache: true, + inputPrice: 15, + outputPrice: 60, + cacheReadsPrice: 7.5, + supportsTemperature: false, + description: "o1", + }, + "o1-mini": { + maxTokens: 65_536, + contextWindow: 128_000, + supportsImages: true, + supportsPromptCache: true, + inputPrice: 1.1, + outputPrice: 4.4, + cacheReadsPrice: 0.55, + supportsTemperature: false, + description: "o1-mini", + }, + "o1-preview": { + maxTokens: 32_768, + contextWindow: 128_000, + supportsImages: true, + supportsPromptCache: true, + inputPrice: 16.5, + outputPrice: 66, + cacheReadsPrice: 8.25, + supportsTemperature: false, + description: "o1-preview", + }, + o3: { + maxTokens: 100_000, + contextWindow: 200_000, + supportsImages: true, + supportsPromptCache: true, + supportsReasoningEffort: ["low", "medium", "high"], + reasoningEffort: "medium", + inputPrice: 2, + outputPrice: 8, + cacheReadsPrice: 0.5, + supportsTemperature: false, + description: "o3", + }, + "o3-mini": { + maxTokens: 100_000, + contextWindow: 200_000, + supportsImages: false, + supportsPromptCache: true, + supportsReasoningEffort: ["low", "medium", "high"], + reasoningEffort: "medium", + inputPrice: 1.1, + outputPrice: 4.4, + cacheReadsPrice: 0.55, + supportsTemperature: false, + description: "o3-mini", + }, + "o4-mini": { + maxTokens: 100_000, + contextWindow: 200_000, + supportsImages: true, + supportsPromptCache: true, + supportsReasoningEffort: ["low", "medium", "high"], + reasoningEffort: "medium", + inputPrice: 1.1, + outputPrice: 4.4, + cacheReadsPrice: 0.28, + supportsTemperature: false, + description: "o4-mini", + }, +} as const satisfies Record + +export type AzureModelId = keyof typeof azureModels + +export const azureDefaultModelId: AzureModelId = "gpt-4o" + +export const azureDefaultModelInfo: ModelInfo = azureModels[azureDefaultModelId] diff --git a/packages/types/src/providers/index.ts b/packages/types/src/providers/index.ts index 2018954bbd..b8d061a6a6 100644 --- a/packages/types/src/providers/index.ts +++ b/packages/types/src/providers/index.ts @@ -1,4 +1,5 @@ export * from "./anthropic.js" +export * from "./azure.js" export * from "./baseten.js" export * from "./bedrock.js" export * from "./cerebras.js" @@ -34,6 +35,7 @@ export * from "./deepinfra.js" export * from "./minimax.js" import { anthropicDefaultModelId } from "./anthropic.js" +import { azureDefaultModelId } from "./azure.js" import { basetenDefaultModelId } from "./baseten.js" import { bedrockDefaultModelId } from "./bedrock.js" import { cerebrasDefaultModelId } from "./cerebras.js" @@ -142,6 +144,8 @@ export function getProviderDefaultModelId( return qwenCodeDefaultModelId case "vercel-ai-gateway": return vercelAiGatewayDefaultModelId + case "azure": + return azureDefaultModelId case "anthropic": case "gemini-cli": case "fake-ai": diff --git a/packages/types/src/providers/openai.ts b/packages/types/src/providers/openai.ts index af9a1ff759..b7532f9c95 100644 --- a/packages/types/src/providers/openai.ts +++ b/packages/types/src/providers/openai.ts @@ -506,9 +506,8 @@ export const openAiModelInfoSaneDefaults: ModelInfo = { outputPrice: 0, } -// https://learn.microsoft.com/en-us/azure/ai-services/openai/api-version-deprecation -// https://learn.microsoft.com/en-us/azure/ai-services/openai/reference#api-specs -export const azureOpenAiDefaultApiVersion = "2024-08-01-preview" +// https://learn.microsoft.com/en-us/azure/ai-foundry/openai/api-version-lifecycle +export const azureOpenAiDefaultApiVersion = "2025-04-01-preview" export const OPENAI_NATIVE_DEFAULT_TEMPERATURE = 0 diff --git a/src/api/providers/__tests__/azure.spec.ts b/src/api/providers/__tests__/azure.spec.ts index c93fe6ca59..1164e40f28 100644 --- a/src/api/providers/__tests__/azure.spec.ts +++ b/src/api/providers/__tests__/azure.spec.ts @@ -274,7 +274,7 @@ describe("AzureHandler", () => { for await (const chunk of stream) { chunks.push(chunk) } - }).rejects.toThrow("Azure OpenAI") + }).rejects.toThrow("Azure AI Foundry") }) }) diff --git a/src/api/providers/azure.ts b/src/api/providers/azure.ts index ac8da0d941..85d1ec5a14 100644 --- a/src/api/providers/azure.ts +++ b/src/api/providers/azure.ts @@ -2,7 +2,7 @@ import { Anthropic } from "@anthropic-ai/sdk" import { createAzure } from "@ai-sdk/azure" import { streamText, generateText, ToolSet } from "ai" -import { azureOpenAiDefaultApiVersion, openAiModelInfoSaneDefaults, type ModelInfo } from "@roo-code/types" +import { azureOpenAiDefaultApiVersion, azureModels, azureDefaultModelInfo, type ModelInfo } from "@roo-code/types" import type { ApiHandlerOptions } from "../../shared/api" @@ -23,7 +23,7 @@ import type { SingleCompletionHandler, ApiHandlerCreateMessageMetadata } from ". const AZURE_DEFAULT_TEMPERATURE = 0 /** - * Azure OpenAI provider using the dedicated @ai-sdk/azure package. + * Azure AI Foundry provider using the dedicated @ai-sdk/azure package. * Provides native support for Azure OpenAI deployments with proper resource-based routing. */ export class AzureHandler extends BaseProvider implements SingleCompletionHandler { @@ -38,25 +38,29 @@ export class AzureHandler extends BaseProvider implements SingleCompletionHandle // The @ai-sdk/azure package uses resourceName-based routing this.provider = createAzure({ resourceName: options.azureResourceName ?? "", - apiKey: options.azureApiKey ?? "not-provided", + apiKey: options.azureApiKey, // Optional — Azure supports managed identity / Entra ID auth apiVersion: options.azureApiVersion ?? azureOpenAiDefaultApiVersion, headers: DEFAULT_HEADERS, }) } override getModel(): { id: string; info: ModelInfo; maxTokens?: number; temperature?: number } { - // Azure uses deployment names as model IDs - // Use azureDeploymentName if provided, otherwise fall back to apiModelId - const id = this.options.azureDeploymentName ?? this.options.apiModelId ?? "" - const info: ModelInfo = openAiModelInfoSaneDefaults + // Azure uses deployment names for API calls, but apiModelId for model capabilities. + // deploymentId is sent to the Azure API; modelId is used for capability lookup. + const deploymentId = this.options.azureDeploymentName ?? this.options.apiModelId ?? "" + const modelId = this.options.apiModelId ?? deploymentId + const info: ModelInfo = + (azureModels as Record)[modelId] ?? + (azureModels as Record)[deploymentId] ?? + azureDefaultModelInfo const params = getModelParams({ format: "openai", - modelId: id, + modelId: deploymentId, // deployment name for the API model: info, settings: this.options, defaultTemperature: AZURE_DEFAULT_TEMPERATURE, }) - return { id, info, ...params } + return { id: deploymentId, info, ...params } } /** @@ -69,7 +73,7 @@ export class AzureHandler extends BaseProvider implements SingleCompletionHandle /** * Process usage metrics from the AI SDK response. - * Azure OpenAI provides standard OpenAI-compatible usage metrics. + * Azure AI Foundry provides standard OpenAI-compatible usage metrics. */ protected processUsageMetrics( usage: { @@ -103,10 +107,13 @@ export class AzureHandler extends BaseProvider implements SingleCompletionHandle /** * Get the max tokens parameter to include in the request. + * Returns undefined if no valid maxTokens is configured to let the API use its default. */ protected getMaxOutputTokens(): number | undefined { const { info } = this.getModel() - return this.options.modelMaxTokens || info.maxTokens || undefined + const maxTokens = this.options.modelMaxTokens || info.maxTokens + // Azure AI Foundry API requires maxOutputTokens >= 1, so filter out invalid values + return maxTokens && maxTokens > 0 ? maxTokens : undefined } /** @@ -157,7 +164,7 @@ export class AzureHandler extends BaseProvider implements SingleCompletionHandle } } catch (error) { // Handle AI SDK errors (AI_RetryError, AI_APICallError, etc.) - throw handleAiSdkError(error, "Azure OpenAI") + throw handleAiSdkError(error, "Azure AI Foundry") } } diff --git a/src/shared/checkExistApiConfig.ts b/src/shared/checkExistApiConfig.ts index ccbda63ae0..54e5bcc036 100644 --- a/src/shared/checkExistApiConfig.ts +++ b/src/shared/checkExistApiConfig.ts @@ -5,11 +5,17 @@ export function checkExistKey(config: ProviderSettings | undefined) { return false } - // Special case for fake-ai, openai-codex, qwen-code, and roo providers which don't need any configuration. + // Special case for providers which don't need standard API key configuration. if (config.apiProvider && ["fake-ai", "openai-codex", "qwen-code", "roo"].includes(config.apiProvider)) { return true } + // Azure supports managed identity / Entra ID auth (no API key needed). + // Consider it configured if resource name or deployment name is set. + if (config.apiProvider === "azure") { + return !!(config.azureResourceName || config.azureDeploymentName || config.azureApiKey) + } + // Check all secret keys from the centralized SECRET_STATE_KEYS array. // Filter out keys that are not part of ProviderSettings (global secrets are stored separately) const providerSecretKeys = SECRET_STATE_KEYS.filter((key) => !GLOBAL_SECRET_KEYS.includes(key as any)) diff --git a/webview-ui/src/components/settings/constants.ts b/webview-ui/src/components/settings/constants.ts index 2d2817912f..5d43432782 100644 --- a/webview-ui/src/components/settings/constants.ts +++ b/webview-ui/src/components/settings/constants.ts @@ -2,6 +2,7 @@ import { type ProviderName, type ModelInfo, anthropicModels, + azureModels, bedrockModels, cerebrasModels, deepSeekModels, @@ -25,6 +26,7 @@ import { export const MODELS_BY_PROVIDER: Partial>> = { anthropic: anthropicModels, + azure: azureModels, bedrock: bedrockModels, cerebras: cerebrasModels, deepseek: deepSeekModels, @@ -50,7 +52,7 @@ export const PROVIDERS = [ { value: "openrouter", label: "OpenRouter", proxy: false }, { value: "deepinfra", label: "DeepInfra", proxy: false }, { value: "anthropic", label: "Anthropic", proxy: false }, - { value: "azure", label: "Azure OpenAI", proxy: false }, + { value: "azure", label: "Azure AI Foundry", proxy: false }, { value: "cerebras", label: "Cerebras", proxy: false }, { value: "gemini", label: "Google Gemini", proxy: false }, { value: "doubao", label: "Doubao", proxy: false }, diff --git a/webview-ui/src/components/settings/providers/Azure.tsx b/webview-ui/src/components/settings/providers/Azure.tsx index 2ab2900122..ed0ca3f2e4 100644 --- a/webview-ui/src/components/settings/providers/Azure.tsx +++ b/webview-ui/src/components/settings/providers/Azure.tsx @@ -4,7 +4,6 @@ import { VSCodeTextField } from "@vscode/webview-ui-toolkit/react" import { type ProviderSettings, azureOpenAiDefaultApiVersion } from "@roo-code/types" import { useAppTranslation } from "@src/i18n/TranslationContext" -import { VSCodeButtonLink } from "@src/components/common/VSCodeButtonLink" import { inputEventTransform } from "../transforms" @@ -71,13 +70,6 @@ export const Azure = ({ apiConfiguration, setApiConfigurationField }: AzureProps
{t("settings:providers.azureApiVersionDescription")}
- {!apiConfiguration?.azureApiKey && ( - - {t("settings:providers.getAzureApiKey")} - - )} ) } diff --git a/webview-ui/src/components/settings/utils/providerModelConfig.ts b/webview-ui/src/components/settings/utils/providerModelConfig.ts index fdeb2647e5..5095420a85 100644 --- a/webview-ui/src/components/settings/utils/providerModelConfig.ts +++ b/webview-ui/src/components/settings/utils/providerModelConfig.ts @@ -1,6 +1,7 @@ import type { ProviderName, ModelInfo, ProviderSettings } from "@roo-code/types" import { anthropicDefaultModelId, + azureDefaultModelId, bedrockDefaultModelId, cerebrasDefaultModelId, deepSeekDefaultModelId, @@ -31,6 +32,10 @@ export interface ProviderServiceConfig { export const PROVIDER_SERVICE_CONFIG: Partial> = { anthropic: { serviceName: "Anthropic", serviceUrl: "https://console.anthropic.com" }, + azure: { + serviceName: "Azure AI Foundry", + serviceUrl: "https://azure.microsoft.com/en-us/products/ai-foundry/models/openai", + }, bedrock: { serviceName: "Amazon Bedrock", serviceUrl: "https://aws.amazon.com/bedrock" }, cerebras: { serviceName: "Cerebras", serviceUrl: "https://cerebras.ai" }, deepseek: { serviceName: "DeepSeek", serviceUrl: "https://platform.deepseek.com" }, @@ -59,6 +64,7 @@ export const PROVIDER_SERVICE_CONFIG: Partial> = { anthropic: anthropicDefaultModelId, + azure: azureDefaultModelId, bedrock: bedrockDefaultModelId, cerebras: cerebrasDefaultModelId, deepseek: deepSeekDefaultModelId, diff --git a/webview-ui/src/components/ui/hooks/useSelectedModel.ts b/webview-ui/src/components/ui/hooks/useSelectedModel.ts index 8f39bdbac2..6718f01d94 100644 --- a/webview-ui/src/components/ui/hooks/useSelectedModel.ts +++ b/webview-ui/src/components/ui/hooks/useSelectedModel.ts @@ -28,6 +28,7 @@ import { featherlessModels, ioIntelligenceModels, basetenModels, + azureModels, qwenCodeModels, litellmDefaultModelInfo, lMStudioDefaultModelInfo, @@ -388,9 +389,14 @@ function getSelectedModel({ return { id, info } } case "azure": { - // Azure uses deployment names configured by the user - const id = apiConfiguration.azureDeploymentName ?? apiConfiguration.apiModelId ?? "" - return { id, info: undefined } + // apiModelId holds the base model selection (from model picker). + // azureDeploymentName is the deployment name sent to the Azure API. + // Only use apiModelId if it matches a known Azure model (prevents stale values from other providers). + const explicitModelId = apiConfiguration.apiModelId + const matchesAzureModel = explicitModelId && azureModels[explicitModelId as keyof typeof azureModels] + const id = matchesAzureModel ? explicitModelId : defaultModelId + const info = azureModels[id as keyof typeof azureModels] + return { id, info: info || undefined } } // case "anthropic": // case "fake-ai": diff --git a/webview-ui/src/i18n/locales/ca/settings.json b/webview-ui/src/i18n/locales/ca/settings.json index 54d2f8dfd1..34e3f55d03 100644 --- a/webview-ui/src/i18n/locales/ca/settings.json +++ b/webview-ui/src/i18n/locales/ca/settings.json @@ -380,11 +380,11 @@ "cerebrasApiKey": "Clau API de Cerebras", "getCerebrasApiKey": "Obtenir clau API de Cerebras", "azureResourceName": "Nom del recurs d'Azure", - "azureResourceNameDescription": "El nom del teu recurs Azure OpenAI (p. ex. 'el-meu-recurs-openai').", + "azureResourceNameDescription": "El nom del teu recurs Azure AI Foundry (p. ex. 'el-meu-recurs-openai').", "azureDeploymentName": "Nom del desplegament d'Azure", "azureDeploymentNameDescription": "El nom del desplegament del model dins del recurs.", "azureApiKey": "Clau API d'Azure", - "getAzureApiKey": "Obtenir accés a Azure OpenAI", + "getAzureApiKey": "Obtenir accés a Azure AI Foundry", "azureApiVersion": "Versió de l'API d'Azure", "azureApiVersionDescription": "La versió de l'API a utilitzar (p. ex. '2024-10-21'). Deixa buit per al valor per defecte.", "chutesApiKey": "Clau API de Chutes", diff --git a/webview-ui/src/i18n/locales/de/settings.json b/webview-ui/src/i18n/locales/de/settings.json index 5ffaaeec81..1ea431e5d2 100644 --- a/webview-ui/src/i18n/locales/de/settings.json +++ b/webview-ui/src/i18n/locales/de/settings.json @@ -382,11 +382,11 @@ "cerebrasApiKey": "Cerebras API-Schlüssel", "getCerebrasApiKey": "Cerebras API-Schlüssel erhalten", "azureResourceName": "Azure Ressourcenname", - "azureResourceNameDescription": "Der Name Ihrer Azure OpenAI-Ressource (z.B. 'meine-openai-ressource').", + "azureResourceNameDescription": "Der Name Ihrer Azure AI Foundry-Ressource (z.B. 'meine-openai-ressource').", "azureDeploymentName": "Azure Bereitstellungsname", "azureDeploymentNameDescription": "Der Name Ihrer Modellbereitstellung innerhalb der Ressource.", "azureApiKey": "Azure API-Schlüssel", - "getAzureApiKey": "Azure OpenAI-Zugang erhalten", + "getAzureApiKey": "Azure AI Foundry-Zugang erhalten", "azureApiVersion": "Azure API-Version", "azureApiVersionDescription": "Die zu verwendende API-Version (z.B. '2024-10-21'). Leer lassen für Standardwert.", "chutesApiKey": "Chutes API-Schlüssel", diff --git a/webview-ui/src/i18n/locales/en/settings.json b/webview-ui/src/i18n/locales/en/settings.json index 25d43dd6d7..015f18effe 100644 --- a/webview-ui/src/i18n/locales/en/settings.json +++ b/webview-ui/src/i18n/locales/en/settings.json @@ -443,11 +443,11 @@ "cerebrasApiKey": "Cerebras API Key", "getCerebrasApiKey": "Get Cerebras API Key", "azureResourceName": "Azure Resource Name", - "azureResourceNameDescription": "The name of your Azure OpenAI resource (e.g., 'my-openai-resource').", + "azureResourceNameDescription": "The name of your Azure AI Foundry resource (e.g., 'my-openai-resource').", "azureDeploymentName": "Azure Deployment Name", "azureDeploymentNameDescription": "The name of your model deployment within the resource.", "azureApiKey": "Azure API Key", - "getAzureApiKey": "Get Azure OpenAI Access", + "getAzureApiKey": "Get Azure AI Foundry Access", "azureApiVersion": "Azure API Version", "azureApiVersionDescription": "The API version to use (e.g., '2024-10-21'). Leave empty for the default.", "chutesApiKey": "Chutes API Key", diff --git a/webview-ui/src/i18n/locales/es/settings.json b/webview-ui/src/i18n/locales/es/settings.json index c9c6fbbe82..6c7d9e9052 100644 --- a/webview-ui/src/i18n/locales/es/settings.json +++ b/webview-ui/src/i18n/locales/es/settings.json @@ -380,11 +380,11 @@ "cerebrasApiKey": "Clave API de Cerebras", "getCerebrasApiKey": "Obtener clave API de Cerebras", "azureResourceName": "Nombre del recurso Azure", - "azureResourceNameDescription": "El nombre de tu recurso Azure OpenAI (ej. 'mi-recurso-openai').", + "azureResourceNameDescription": "El nombre de tu recurso Azure AI Foundry (ej. 'mi-recurso-openai').", "azureDeploymentName": "Nombre del despliegue Azure", "azureDeploymentNameDescription": "El nombre del despliegue de tu modelo dentro del recurso.", "azureApiKey": "Clave API de Azure", - "getAzureApiKey": "Obtener acceso a Azure OpenAI", + "getAzureApiKey": "Obtener acceso a Azure AI Foundry", "azureApiVersion": "Versión de API de Azure", "azureApiVersionDescription": "La versión de la API a usar (ej. '2024-10-21'). Dejar vacío para usar el valor predeterminado.", "chutesApiKey": "Clave API de Chutes", diff --git a/webview-ui/src/i18n/locales/fr/settings.json b/webview-ui/src/i18n/locales/fr/settings.json index 063dc69b44..852f526bbc 100644 --- a/webview-ui/src/i18n/locales/fr/settings.json +++ b/webview-ui/src/i18n/locales/fr/settings.json @@ -380,11 +380,11 @@ "cerebrasApiKey": "Clé API Cerebras", "getCerebrasApiKey": "Obtenir la clé API Cerebras", "azureResourceName": "Nom de la ressource Azure", - "azureResourceNameDescription": "Le nom de votre ressource Azure OpenAI (ex. 'ma-ressource-openai').", + "azureResourceNameDescription": "Le nom de votre ressource Azure AI Foundry (ex. 'ma-ressource-openai').", "azureDeploymentName": "Nom du déploiement Azure", "azureDeploymentNameDescription": "Le nom du déploiement de votre modèle dans la ressource.", "azureApiKey": "Clé API Azure", - "getAzureApiKey": "Obtenir l'accès Azure OpenAI", + "getAzureApiKey": "Obtenir l'accès Azure AI Foundry", "azureApiVersion": "Version de l'API Azure", "azureApiVersionDescription": "La version de l'API à utiliser (ex. '2024-10-21'). Laisser vide pour la valeur par défaut.", "chutesApiKey": "Clé API Chutes", diff --git a/webview-ui/src/i18n/locales/hi/settings.json b/webview-ui/src/i18n/locales/hi/settings.json index a8ea142876..f1859fda13 100644 --- a/webview-ui/src/i18n/locales/hi/settings.json +++ b/webview-ui/src/i18n/locales/hi/settings.json @@ -380,11 +380,11 @@ "cerebrasApiKey": "Cerebras API कुंजी", "getCerebrasApiKey": "Cerebras API कुंजी प्राप्त करें", "azureResourceName": "Azure रिसोर्स नाम", - "azureResourceNameDescription": "आपके Azure OpenAI रिसोर्स का नाम (उदा. 'my-openai-resource')।", + "azureResourceNameDescription": "आपके Azure AI Foundry रिसोर्स का नाम (उदा. 'my-openai-resource')।", "azureDeploymentName": "Azure डिप्लॉयमेंट नाम", "azureDeploymentNameDescription": "रिसोर्स के अंदर आपके मॉडल डिप्लॉयमेंट का नाम।", "azureApiKey": "Azure API कुंजी", - "getAzureApiKey": "Azure OpenAI एक्सेस प्राप्त करें", + "getAzureApiKey": "Azure AI Foundry एक्सेस प्राप्त करें", "azureApiVersion": "Azure API संस्करण", "azureApiVersionDescription": "उपयोग करने के लिए API संस्करण (उदा. '2024-10-21')। डिफ़ॉल्ट के लिए खाली छोड़ें।", "chutesApiKey": "Chutes API कुंजी", diff --git a/webview-ui/src/i18n/locales/id/settings.json b/webview-ui/src/i18n/locales/id/settings.json index 349ccd2ada..ce9458167a 100644 --- a/webview-ui/src/i18n/locales/id/settings.json +++ b/webview-ui/src/i18n/locales/id/settings.json @@ -380,11 +380,11 @@ "cerebrasApiKey": "Cerebras API Key", "getCerebrasApiKey": "Dapatkan Cerebras API Key", "azureResourceName": "Nama Resource Azure", - "azureResourceNameDescription": "Nama resource Azure OpenAI Anda (contoh: 'my-openai-resource').", + "azureResourceNameDescription": "Nama resource Azure AI Foundry Anda (contoh: 'my-openai-resource').", "azureDeploymentName": "Nama Deployment Azure", "azureDeploymentNameDescription": "Nama deployment model dalam resource.", "azureApiKey": "Azure API Key", - "getAzureApiKey": "Dapatkan Akses Azure OpenAI", + "getAzureApiKey": "Dapatkan Akses Azure AI Foundry", "azureApiVersion": "Versi API Azure", "azureApiVersionDescription": "Versi API yang akan digunakan (contoh: '2024-10-21'). Biarkan kosong untuk nilai default.", "chutesApiKey": "Chutes API Key", diff --git a/webview-ui/src/i18n/locales/it/settings.json b/webview-ui/src/i18n/locales/it/settings.json index 2c1f14862f..c5fcd2c130 100644 --- a/webview-ui/src/i18n/locales/it/settings.json +++ b/webview-ui/src/i18n/locales/it/settings.json @@ -380,11 +380,11 @@ "cerebrasApiKey": "Chiave API Cerebras", "getCerebrasApiKey": "Ottieni chiave API Cerebras", "azureResourceName": "Nome risorsa Azure", - "azureResourceNameDescription": "Il nome della tua risorsa Azure OpenAI (es. 'mia-risorsa-openai').", + "azureResourceNameDescription": "Il nome della tua risorsa Azure AI Foundry (es. 'mia-risorsa-openai').", "azureDeploymentName": "Nome distribuzione Azure", "azureDeploymentNameDescription": "Il nome della distribuzione del modello all'interno della risorsa.", "azureApiKey": "Chiave API Azure", - "getAzureApiKey": "Ottieni accesso Azure OpenAI", + "getAzureApiKey": "Ottieni accesso Azure AI Foundry", "azureApiVersion": "Versione API Azure", "azureApiVersionDescription": "La versione dell'API da utilizzare (es. '2024-10-21'). Lascia vuoto per il valore predefinito.", "chutesApiKey": "Chiave API Chutes", diff --git a/webview-ui/src/i18n/locales/ja/settings.json b/webview-ui/src/i18n/locales/ja/settings.json index b773437ba2..1b0c5b9a35 100644 --- a/webview-ui/src/i18n/locales/ja/settings.json +++ b/webview-ui/src/i18n/locales/ja/settings.json @@ -380,11 +380,11 @@ "cerebrasApiKey": "Cerebras APIキー", "getCerebrasApiKey": "Cerebras APIキーを取得", "azureResourceName": "Azureリソース名", - "azureResourceNameDescription": "Azure OpenAIリソースの名前(例:'my-openai-resource')。", + "azureResourceNameDescription": "Azure AI Foundryリソースの名前(例:'my-openai-resource')。", "azureDeploymentName": "Azureデプロイメント名", "azureDeploymentNameDescription": "リソース内のモデルデプロイメントの名前。", "azureApiKey": "Azure APIキー", - "getAzureApiKey": "Azure OpenAIアクセスを取得", + "getAzureApiKey": "Azure AI Foundryアクセスを取得", "azureApiVersion": "Azure APIバージョン", "azureApiVersionDescription": "使用するAPIバージョン(例:'2024-10-21')。デフォルトを使用する場合は空にしてください。", "chutesApiKey": "Chutes APIキー", diff --git a/webview-ui/src/i18n/locales/ko/settings.json b/webview-ui/src/i18n/locales/ko/settings.json index 4da722111b..ab480e8a73 100644 --- a/webview-ui/src/i18n/locales/ko/settings.json +++ b/webview-ui/src/i18n/locales/ko/settings.json @@ -380,11 +380,11 @@ "cerebrasApiKey": "Cerebras API 키", "getCerebrasApiKey": "Cerebras API 키 가져오기", "azureResourceName": "Azure 리소스 이름", - "azureResourceNameDescription": "Azure OpenAI 리소스 이름 (예: 'my-openai-resource').", + "azureResourceNameDescription": "Azure AI Foundry 리소스 이름 (예: 'my-openai-resource').", "azureDeploymentName": "Azure 배포 이름", "azureDeploymentNameDescription": "리소스 내 모델 배포 이름.", "azureApiKey": "Azure API 키", - "getAzureApiKey": "Azure OpenAI 액세스 받기", + "getAzureApiKey": "Azure AI Foundry 액세스 받기", "azureApiVersion": "Azure API 버전", "azureApiVersionDescription": "사용할 API 버전 (예: '2024-10-21'). 기본값을 사용하려면 비워두세요.", "chutesApiKey": "Chutes API 키", diff --git a/webview-ui/src/i18n/locales/nl/settings.json b/webview-ui/src/i18n/locales/nl/settings.json index fad1281b9b..f74d57f11a 100644 --- a/webview-ui/src/i18n/locales/nl/settings.json +++ b/webview-ui/src/i18n/locales/nl/settings.json @@ -380,11 +380,11 @@ "cerebrasApiKey": "Cerebras API-sleutel", "getCerebrasApiKey": "Cerebras API-sleutel verkrijgen", "azureResourceName": "Azure Resource-naam", - "azureResourceNameDescription": "De naam van je Azure OpenAI resource (bijv. 'mijn-openai-resource').", + "azureResourceNameDescription": "De naam van je Azure AI Foundry resource (bijv. 'mijn-openai-resource').", "azureDeploymentName": "Azure Deployment-naam", "azureDeploymentNameDescription": "De naam van je model deployment binnen de resource.", "azureApiKey": "Azure API-sleutel", - "getAzureApiKey": "Azure OpenAI-toegang verkrijgen", + "getAzureApiKey": "Azure AI Foundry-toegang verkrijgen", "azureApiVersion": "Azure API-versie", "azureApiVersionDescription": "De API-versie om te gebruiken (bijv. '2024-10-21'). Laat leeg voor standaardwaarde.", "chutesApiKey": "Chutes API-sleutel", diff --git a/webview-ui/src/i18n/locales/pl/settings.json b/webview-ui/src/i18n/locales/pl/settings.json index 81cdd16d79..8c971d1eeb 100644 --- a/webview-ui/src/i18n/locales/pl/settings.json +++ b/webview-ui/src/i18n/locales/pl/settings.json @@ -380,11 +380,11 @@ "cerebrasApiKey": "Klucz API Cerebras", "getCerebrasApiKey": "Pobierz klucz API Cerebras", "azureResourceName": "Nazwa zasobu Azure", - "azureResourceNameDescription": "Nazwa Twojego zasobu Azure OpenAI (np. 'moj-zasob-openai').", + "azureResourceNameDescription": "Nazwa Twojego zasobu Azure AI Foundry (np. 'moj-zasob-openai').", "azureDeploymentName": "Nazwa wdrożenia Azure", "azureDeploymentNameDescription": "Nazwa wdrożenia modelu w zasobie.", "azureApiKey": "Klucz API Azure", - "getAzureApiKey": "Uzyskaj dostęp do Azure OpenAI", + "getAzureApiKey": "Uzyskaj dostęp do Azure AI Foundry", "azureApiVersion": "Wersja API Azure", "azureApiVersionDescription": "Wersja API do użycia (np. '2024-10-21'). Pozostaw puste dla wartości domyślnej.", "chutesApiKey": "Klucz API Chutes", diff --git a/webview-ui/src/i18n/locales/pt-BR/settings.json b/webview-ui/src/i18n/locales/pt-BR/settings.json index 053e40e193..90efc72c21 100644 --- a/webview-ui/src/i18n/locales/pt-BR/settings.json +++ b/webview-ui/src/i18n/locales/pt-BR/settings.json @@ -380,11 +380,11 @@ "cerebrasApiKey": "Chave de API Cerebras", "getCerebrasApiKey": "Obter chave de API Cerebras", "azureResourceName": "Nome do recurso Azure", - "azureResourceNameDescription": "O nome do seu recurso Azure OpenAI (ex: 'meu-recurso-openai').", + "azureResourceNameDescription": "O nome do seu recurso Azure AI Foundry (ex: 'meu-recurso-openai').", "azureDeploymentName": "Nome da implantação Azure", "azureDeploymentNameDescription": "O nome da implantação do modelo dentro do recurso.", "azureApiKey": "Chave de API Azure", - "getAzureApiKey": "Obter acesso ao Azure OpenAI", + "getAzureApiKey": "Obter acesso ao Azure AI Foundry", "azureApiVersion": "Versão da API Azure", "azureApiVersionDescription": "A versão da API a ser usada (ex: '2024-10-21'). Deixe vazio para o padrão.", "chutesApiKey": "Chave de API Chutes", diff --git a/webview-ui/src/i18n/locales/ru/settings.json b/webview-ui/src/i18n/locales/ru/settings.json index 89ef261c52..94e2ee30cd 100644 --- a/webview-ui/src/i18n/locales/ru/settings.json +++ b/webview-ui/src/i18n/locales/ru/settings.json @@ -380,11 +380,11 @@ "cerebrasApiKey": "Cerebras API-ключ", "getCerebrasApiKey": "Получить Cerebras API-ключ", "azureResourceName": "Имя ресурса Azure", - "azureResourceNameDescription": "Имя вашего ресурса Azure OpenAI (напр. 'my-openai-resource').", + "azureResourceNameDescription": "Имя вашего ресурса Azure AI Foundry (напр. 'my-openai-resource').", "azureDeploymentName": "Имя развертывания Azure", "azureDeploymentNameDescription": "Имя развертывания модели внутри ресурса.", "azureApiKey": "API-ключ Azure", - "getAzureApiKey": "Получить доступ к Azure OpenAI", + "getAzureApiKey": "Получить доступ к Azure AI Foundry", "azureApiVersion": "Версия API Azure", "azureApiVersionDescription": "Версия API для использования (напр. '2024-10-21'). Оставьте пустым для значения по умолчанию.", "chutesApiKey": "Chutes API-ключ", diff --git a/webview-ui/src/i18n/locales/tr/settings.json b/webview-ui/src/i18n/locales/tr/settings.json index 0a3dd960c8..e88eba6e04 100644 --- a/webview-ui/src/i18n/locales/tr/settings.json +++ b/webview-ui/src/i18n/locales/tr/settings.json @@ -380,11 +380,11 @@ "cerebrasApiKey": "Cerebras API Anahtarı", "getCerebrasApiKey": "Cerebras API Anahtarını Al", "azureResourceName": "Azure Kaynak Adı", - "azureResourceNameDescription": "Azure OpenAI kaynak adınız (örn. 'benim-openai-kaynagim').", + "azureResourceNameDescription": "Azure AI Foundry kaynak adınız (örn. 'benim-openai-kaynagim').", "azureDeploymentName": "Azure Dağıtım Adı", "azureDeploymentNameDescription": "Kaynak içindeki model dağıtım adınız.", "azureApiKey": "Azure API Anahtarı", - "getAzureApiKey": "Azure OpenAI Erişimi Al", + "getAzureApiKey": "Azure AI Foundry Erişimi Al", "azureApiVersion": "Azure API Sürümü", "azureApiVersionDescription": "Kullanılacak API sürümü (örn. '2024-10-21'). Varsayılan için boş bırakın.", "chutesApiKey": "Chutes API Anahtarı", diff --git a/webview-ui/src/i18n/locales/vi/settings.json b/webview-ui/src/i18n/locales/vi/settings.json index 07d5fb749a..e3345aa80d 100644 --- a/webview-ui/src/i18n/locales/vi/settings.json +++ b/webview-ui/src/i18n/locales/vi/settings.json @@ -380,11 +380,11 @@ "cerebrasApiKey": "Khóa API Cerebras", "getCerebrasApiKey": "Lấy khóa API Cerebras", "azureResourceName": "Tên tài nguyên Azure", - "azureResourceNameDescription": "Tên tài nguyên Azure OpenAI của bạn (ví dụ: 'my-openai-resource').", + "azureResourceNameDescription": "Tên tài nguyên Azure AI Foundry của bạn (ví dụ: 'my-openai-resource').", "azureDeploymentName": "Tên triển khai Azure", "azureDeploymentNameDescription": "Tên triển khai mô hình trong tài nguyên.", "azureApiKey": "Khóa API Azure", - "getAzureApiKey": "Lấy quyền truy cập Azure OpenAI", + "getAzureApiKey": "Lấy quyền truy cập Azure AI Foundry", "azureApiVersion": "Phiên bản API Azure", "azureApiVersionDescription": "Phiên bản API để sử dụng (ví dụ: '2024-10-21'). Để trống để dùng giá trị mặc định.", "chutesApiKey": "Khóa API Chutes", diff --git a/webview-ui/src/i18n/locales/zh-CN/settings.json b/webview-ui/src/i18n/locales/zh-CN/settings.json index a6600c228e..f8086c1218 100644 --- a/webview-ui/src/i18n/locales/zh-CN/settings.json +++ b/webview-ui/src/i18n/locales/zh-CN/settings.json @@ -380,11 +380,11 @@ "cerebrasApiKey": "Cerebras API 密钥", "getCerebrasApiKey": "获取 Cerebras API 密钥", "azureResourceName": "Azure 资源名称", - "azureResourceNameDescription": "您的 Azure OpenAI 资源名称(例如:'my-openai-resource')。", + "azureResourceNameDescription": "您的 Azure AI Foundry 资源名称(例如:'my-openai-resource')。", "azureDeploymentName": "Azure 部署名称", "azureDeploymentNameDescription": "资源中的模型部署名称。", "azureApiKey": "Azure API 密钥", - "getAzureApiKey": "获取 Azure OpenAI 访问权限", + "getAzureApiKey": "获取 Azure AI Foundry 访问权限", "azureApiVersion": "Azure API 版本", "azureApiVersionDescription": "要使用的 API 版本(例如:'2024-10-21')。留空使用默认值。", "chutesApiKey": "Chutes API 密钥", diff --git a/webview-ui/src/i18n/locales/zh-TW/settings.json b/webview-ui/src/i18n/locales/zh-TW/settings.json index c3d1b7ac82..3476e0c8a1 100644 --- a/webview-ui/src/i18n/locales/zh-TW/settings.json +++ b/webview-ui/src/i18n/locales/zh-TW/settings.json @@ -390,11 +390,11 @@ "cerebrasApiKey": "Cerebras API 金鑰", "getCerebrasApiKey": "取得 Cerebras API 金鑰", "azureResourceName": "Azure 資源名稱", - "azureResourceNameDescription": "您的 Azure OpenAI 資源名稱(例如:'my-openai-resource')。", + "azureResourceNameDescription": "您的 Azure AI Foundry 資源名稱(例如:'my-openai-resource')。", "azureDeploymentName": "Azure 部署名稱", "azureDeploymentNameDescription": "資源中的模型部署名稱。", "azureApiKey": "Azure API 金鑰", - "getAzureApiKey": "取得 Azure OpenAI 存取權限", + "getAzureApiKey": "取得 Azure AI Foundry 存取權限", "azureApiVersion": "Azure API 版本", "azureApiVersionDescription": "要使用的 API 版本(例如:'2024-10-21')。留空使用預設值。", "chutesApiKey": "Chutes API 金鑰", diff --git a/webview-ui/src/utils/validate.ts b/webview-ui/src/utils/validate.ts index 2acbda4fb4..43b84d316d 100644 --- a/webview-ui/src/utils/validate.ts +++ b/webview-ui/src/utils/validate.ts @@ -156,9 +156,15 @@ function validateModelsAndKeysProvided(apiConfiguration: ProviderSettings): stri } break case "azure": - if (!apiConfiguration.azureApiKey) { - return i18next.t("settings:validation.apiKey") + // Don't show validation errors when provider is freshly selected (all fields empty) + if ( + !apiConfiguration.azureApiKey && + !apiConfiguration.azureResourceName && + !apiConfiguration.azureDeploymentName + ) { + break } + // API key is optional — Azure supports managed identity / Entra ID auth if (!apiConfiguration.azureResourceName) { return i18next.t("settings:validation.azureResourceName") }