feat: Add Azure AI Foundry support for Anthropic provider

- Add anthropicUseAzureFoundry and anthropicAzureDeploymentName settings
- Update AnthropicHandler to use Azure deployment names when configured
- Add UI controls for Azure Foundry configuration
- Add translations for all supported locales
- Add comprehensive tests for Azure Foundry functionality

Fixes #9940
This commit is contained in:
Roo Code 2025-12-09 10:57:54 +00:00
parent c103a4a639
commit 79e5301415
22 changed files with 163 additions and 1 deletions

View file

@ -199,6 +199,8 @@ const anthropicSchema = apiModelIdProviderModelSchema.extend({
anthropicBaseUrl: z.string().optional(),
anthropicUseAuthToken: z.boolean().optional(),
anthropicBeta1MContext: z.boolean().optional(), // Enable 'context-1m-2025-08-07' beta for 1M context window.
anthropicUseAzureFoundry: z.boolean().optional(), // Enable Azure AI Foundry mode
anthropicAzureDeploymentName: z.string().optional(), // Override model ID with Azure deployment name
})
const claudeCodeSchema = apiModelIdProviderModelSchema.extend({

View file

@ -237,6 +237,72 @@ describe("AnthropicHandler", () => {
expect(model.info.supportsPromptCache).toBe(true)
})
describe("Azure Foundry support", () => {
it("should use Azure deployment name when Azure Foundry mode is enabled", () => {
const handler = new AnthropicHandler({
apiKey: "test-api-key",
apiModelId: "claude-3-5-sonnet-20241022",
anthropicUseAzureFoundry: true,
anthropicAzureDeploymentName: "my-claude-deployment",
})
const model = handler.getModel()
expect(model.id).toBe("my-claude-deployment")
// Should still use the original model info
expect(model.info.maxTokens).toBe(8192)
expect(model.info.contextWindow).toBe(200_000)
})
it("should use original model ID when Azure Foundry is enabled but no deployment name provided", () => {
const handler = new AnthropicHandler({
apiKey: "test-api-key",
apiModelId: "claude-3-5-sonnet-20241022",
anthropicUseAzureFoundry: true,
})
const model = handler.getModel()
expect(model.id).toBe("claude-3-5-sonnet-20241022")
})
it("should use original model ID when Azure Foundry is disabled even with deployment name", () => {
const handler = new AnthropicHandler({
apiKey: "test-api-key",
apiModelId: "claude-3-5-sonnet-20241022",
anthropicUseAzureFoundry: false,
anthropicAzureDeploymentName: "my-claude-deployment",
})
const model = handler.getModel()
expect(model.id).toBe("claude-3-5-sonnet-20241022")
})
it("should handle Azure deployment name with thinking model", () => {
const handler = new AnthropicHandler({
apiKey: "test-api-key",
apiModelId: "claude-3-7-sonnet-20250219:thinking",
anthropicUseAzureFoundry: true,
anthropicAzureDeploymentName: "azure-thinking-model",
})
const model = handler.getModel()
expect(model.id).toBe("azure-thinking-model")
// Should still have the thinking model betas
expect(model.betas).toEqual(["output-128k-2025-02-19"])
})
it("should work with Azure Foundry and 1M context beta together", () => {
const handler = new AnthropicHandler({
apiKey: "test-api-key",
apiModelId: "claude-sonnet-4-5",
anthropicUseAzureFoundry: true,
anthropicAzureDeploymentName: "azure-sonnet-4-5",
anthropicBeta1MContext: true,
})
const model = handler.getModel()
expect(model.id).toBe("azure-sonnet-4-5")
// Should still apply 1M context settings
expect(model.info.contextWindow).toBe(1000000)
expect(model.info.inputPrice).toBe(6.0)
expect(model.info.outputPrice).toBe(22.5)
})
})
it("honors custom maxTokens for thinking models", () => {
const handler = new AnthropicHandler({
apiKey: "test-api-key",

View file

@ -336,8 +336,16 @@ export class AnthropicHandler extends BaseProvider implements SingleCompletionHa
// reasoning model and that reasoning is required to be enabled.
// The actual model ID honored by Anthropic's API does not have this
// suffix.
const baseId = id === "claude-3-7-sonnet-20250219:thinking" ? "claude-3-7-sonnet-20250219" : id
// If Azure Foundry mode is enabled and a deployment name is provided, use it
const finalId =
this.options.anthropicUseAzureFoundry && this.options.anthropicAzureDeploymentName
? this.options.anthropicAzureDeploymentName
: baseId
return {
id: id === "claude-3-7-sonnet-20250219:thinking" ? "claude-3-7-sonnet-20250219" : id,
id: finalId,
info,
betas: id === "claude-3-7-sonnet-20250219:thinking" ? ["output-128k-2025-02-19"] : undefined,
...params,

View file

@ -21,6 +21,7 @@ export const Anthropic = ({ apiConfiguration, setApiConfigurationField }: Anthro
const selectedModel = useSelectedModel(apiConfiguration)
const [anthropicBaseUrlSelected, setAnthropicBaseUrlSelected] = useState(!!apiConfiguration?.anthropicBaseUrl)
const [azureFoundryEnabled, setAzureFoundryEnabled] = useState(!!apiConfiguration?.anthropicUseAzureFoundry)
// Check if the current model supports 1M context beta
const supports1MContextBeta =
@ -86,6 +87,37 @@ export const Anthropic = ({ apiConfiguration, setApiConfigurationField }: Anthro
</>
)}
</div>
{anthropicBaseUrlSelected && (
<div>
<Checkbox
checked={azureFoundryEnabled}
onChange={(checked: boolean) => {
setAzureFoundryEnabled(checked)
setApiConfigurationField("anthropicUseAzureFoundry", checked)
if (!checked) {
setApiConfigurationField("anthropicAzureDeploymentName", "")
}
}}>
{t("settings:providers.anthropicUseAzureFoundry")}
</Checkbox>
{azureFoundryEnabled && (
<>
<VSCodeTextField
value={apiConfiguration?.anthropicAzureDeploymentName || ""}
onInput={handleInputChange("anthropicAzureDeploymentName")}
placeholder="claude-opus-4-5"
className="w-full mt-2">
<label className="block font-medium mb-1">
{t("settings:providers.anthropicAzureDeploymentName")}
</label>
</VSCodeTextField>
<div className="text-sm text-vscode-descriptionForeground mt-1">
{t("settings:providers.anthropicAzureDeploymentNameDescription")}
</div>
</>
)}
</div>
)}
{supports1MContextBeta && (
<div>
<Checkbox

View file

@ -308,6 +308,9 @@
"anthropicApiKey": "Clau API d'Anthropic",
"getAnthropicApiKey": "Obtenir clau API d'Anthropic",
"anthropicUseAuthToken": "Passar la clau API d'Anthropic com a capçalera d'autorització en lloc de X-Api-Key",
"anthropicUseAzureFoundry": "Utilitzar Azure AI Foundry",
"anthropicAzureDeploymentName": "Nom de desplegament d'Azure",
"anthropicAzureDeploymentNameDescription": "Introduïu el nom del desplegament d'Azure Foundry (p. ex., claude-opus-4-5). Això anul·larà l'ID del model seleccionat.",
"anthropic1MContextBetaLabel": "Activa la finestra de context d'1M (Beta)",
"anthropic1MContextBetaDescription": "Amplia la finestra de context a 1 milió de tokens per a Claude Sonnet 4",
"awsBedrock1MContextBetaLabel": "Activa la finestra de context d'1M (Beta)",

View file

@ -310,6 +310,9 @@
"anthropicApiKey": "Anthropic API-Schlüssel",
"getAnthropicApiKey": "Anthropic API-Schlüssel erhalten",
"anthropicUseAuthToken": "Anthropic API-Schlüssel als Authorization-Header anstelle von X-Api-Key übergeben",
"anthropicUseAzureFoundry": "Azure AI Foundry verwenden",
"anthropicAzureDeploymentName": "Azure-Bereitstellungsname",
"anthropicAzureDeploymentNameDescription": "Geben Sie Ihren Azure Foundry-Bereitstellungsnamen ein (z.B. claude-opus-4-5). Dies überschreibt die ausgewählte Modell-ID.",
"anthropic1MContextBetaLabel": "1M Kontextfenster aktivieren (Beta)",
"anthropic1MContextBetaDescription": "Erweitert das Kontextfenster für Claude Sonnet 4 auf 1 Million Token",
"awsBedrock1MContextBetaLabel": "1M Kontextfenster aktivieren (Beta)",

View file

@ -313,6 +313,9 @@
"anthropicApiKey": "Anthropic API Key",
"getAnthropicApiKey": "Get Anthropic API Key",
"anthropicUseAuthToken": "Pass Anthropic API Key as Authorization header instead of X-Api-Key",
"anthropicUseAzureFoundry": "Use Azure AI Foundry",
"anthropicAzureDeploymentName": "Azure Deployment Name",
"anthropicAzureDeploymentNameDescription": "Enter your Azure Foundry deployment name (e.g., claude-opus-4-5). This will override the selected model ID.",
"anthropic1MContextBetaLabel": "Enable 1M context window (Beta)",
"anthropic1MContextBetaDescription": "Extends context window to 1 million tokens for Claude Sonnet 4",
"awsBedrock1MContextBetaLabel": "Enable 1M context window (Beta)",

View file

@ -308,6 +308,9 @@
"anthropicApiKey": "Clave API de Anthropic",
"getAnthropicApiKey": "Obtener clave API de Anthropic",
"anthropicUseAuthToken": "Pasar la clave API de Anthropic como encabezado de autorización en lugar de X-Api-Key",
"anthropicUseAzureFoundry": "Usar Azure AI Foundry",
"anthropicAzureDeploymentName": "Nombre de implementación de Azure",
"anthropicAzureDeploymentNameDescription": "Ingrese el nombre de su implementación de Azure Foundry (p. ej., claude-opus-4-5). Esto anulará el ID del modelo seleccionado.",
"anthropic1MContextBetaLabel": "Habilitar ventana de contexto de 1M (Beta)",
"anthropic1MContextBetaDescription": "Amplía la ventana de contexto a 1 millón de tokens para Claude Sonnet 4",
"awsBedrock1MContextBetaLabel": "Habilitar ventana de contexto de 1M (Beta)",

View file

@ -308,6 +308,9 @@
"anthropicApiKey": "Clé API Anthropic",
"getAnthropicApiKey": "Obtenir la clé API Anthropic",
"anthropicUseAuthToken": "Passer la clé API Anthropic comme en-tête d'autorisation au lieu de X-Api-Key",
"anthropicUseAzureFoundry": "Utiliser Azure AI Foundry",
"anthropicAzureDeploymentName": "Nom du déploiement Azure",
"anthropicAzureDeploymentNameDescription": "Entrez le nom de votre déploiement Azure Foundry (par ex., claude-opus-4-5). Cela remplacera l'ID du modèle sélectionné.",
"anthropic1MContextBetaLabel": "Activer la fenêtre de contexte de 1M (Bêta)",
"anthropic1MContextBetaDescription": "Étend la fenêtre de contexte à 1 million de tokens pour Claude Sonnet 4",
"awsBedrock1MContextBetaLabel": "Activer la fenêtre de contexte de 1M (Bêta)",

View file

@ -308,6 +308,9 @@
"anthropicApiKey": "Anthropic API कुंजी",
"getAnthropicApiKey": "Anthropic API कुंजी प्राप्त करें",
"anthropicUseAuthToken": "X-Api-Key के बजाय Anthropic API कुंजी को Authorization हेडर के रूप में पास करें",
"anthropicUseAzureFoundry": "Azure AI Foundry का उपयोग करें",
"anthropicAzureDeploymentName": "Azure परिनियोजन नाम",
"anthropicAzureDeploymentNameDescription": "अपना Azure Foundry परिनियोजन नाम दर्ज करें (जैसे, claude-opus-4-5)। यह चयनित मॉडल ID को ओवरराइड कर देगा।",
"anthropic1MContextBetaLabel": "1M संदर्भ विंडो सक्षम करें (बीटा)",
"anthropic1MContextBetaDescription": "Claude Sonnet 4 के लिए संदर्भ विंडो को 1 मिलियन टोकन तक बढ़ाता है",
"awsBedrock1MContextBetaLabel": "1M संदर्भ विंडो सक्षम करें (बीटा)",

View file

@ -312,6 +312,9 @@
"anthropicApiKey": "Anthropic API Key",
"getAnthropicApiKey": "Dapatkan Anthropic API Key",
"anthropicUseAuthToken": "Kirim Anthropic API Key sebagai Authorization header alih-alih X-Api-Key",
"anthropicUseAzureFoundry": "Gunakan Azure AI Foundry",
"anthropicAzureDeploymentName": "Nama Deployment Azure",
"anthropicAzureDeploymentNameDescription": "Masukkan nama deployment Azure Foundry Anda (mis. claude-opus-4-5). Ini akan menggantikan ID model yang dipilih.",
"anthropic1MContextBetaLabel": "Aktifkan jendela konteks 1M (Beta)",
"anthropic1MContextBetaDescription": "Memperluas jendela konteks menjadi 1 juta token untuk Claude Sonnet 4",
"awsBedrock1MContextBetaLabel": "Aktifkan jendela konteks 1M (Beta)",

View file

@ -308,6 +308,9 @@
"anthropicApiKey": "Chiave API Anthropic",
"getAnthropicApiKey": "Ottieni chiave API Anthropic",
"anthropicUseAuthToken": "Passa la chiave API Anthropic come header di autorizzazione invece di X-Api-Key",
"anthropicUseAzureFoundry": "Usa Azure AI Foundry",
"anthropicAzureDeploymentName": "Nome distribuzione Azure",
"anthropicAzureDeploymentNameDescription": "Inserisci il nome della distribuzione Azure Foundry (es. claude-opus-4-5). Questo sovrascriverà l'ID del modello selezionato.",
"anthropic1MContextBetaLabel": "Abilita finestra di contesto da 1M (Beta)",
"anthropic1MContextBetaDescription": "Estende la finestra di contesto a 1 milione di token per Claude Sonnet 4",
"awsBedrock1MContextBetaLabel": "Abilita finestra di contesto da 1M (Beta)",

View file

@ -308,6 +308,9 @@
"anthropicApiKey": "Anthropic APIキー",
"getAnthropicApiKey": "Anthropic APIキーを取得",
"anthropicUseAuthToken": "Anthropic APIキーをX-Api-Keyの代わりにAuthorizationヘッダーとして渡す",
"anthropicUseAzureFoundry": "Azure AI Foundryを使用",
"anthropicAzureDeploymentName": "Azureデプロイメント名",
"anthropicAzureDeploymentNameDescription": "Azure Foundryデプロイメント名を入力してくださいclaude-opus-4-5。これにより、選択したモデルIDが上書きされます。",
"anthropic1MContextBetaLabel": "1Mコンテキストウィンドウを有効にするベータ版",
"anthropic1MContextBetaDescription": "Claude Sonnet 4のコンテキストウィンドウを100万トークンに拡張します",
"awsBedrock1MContextBetaLabel": "1Mコンテキストウィンドウを有効にするベータ版",

View file

@ -308,6 +308,9 @@
"anthropicApiKey": "Anthropic API 키",
"getAnthropicApiKey": "Anthropic API 키 받기",
"anthropicUseAuthToken": "X-Api-Key 대신 Authorization 헤더로 Anthropic API 키 전달",
"anthropicUseAzureFoundry": "Azure AI Foundry 사용",
"anthropicAzureDeploymentName": "Azure 배포 이름",
"anthropicAzureDeploymentNameDescription": "Azure Foundry 배포 이름을 입력하세요 (예: claude-opus-4-5). 이것은 선택한 모델 ID를 재정의합니다.",
"anthropic1MContextBetaLabel": "1M 컨텍스트 창 활성화 (베타)",
"anthropic1MContextBetaDescription": "Claude Sonnet 4의 컨텍스트 창을 100만 토큰으로 확장",
"awsBedrock1MContextBetaLabel": "1M 컨텍스트 창 활성화 (베타)",

View file

@ -308,6 +308,9 @@
"anthropicApiKey": "Anthropic API-sleutel",
"getAnthropicApiKey": "Anthropic API-sleutel ophalen",
"anthropicUseAuthToken": "Anthropic API-sleutel als Authorization-header doorgeven in plaats van X-Api-Key",
"anthropicUseAzureFoundry": "Azure AI Foundry gebruiken",
"anthropicAzureDeploymentName": "Azure-implementatienaam",
"anthropicAzureDeploymentNameDescription": "Voer uw Azure Foundry-implementatienaam in (bijv. claude-opus-4-5). Dit overschrijft de geselecteerde model-ID.",
"anthropic1MContextBetaLabel": "1M contextvenster inschakelen (bèta)",
"anthropic1MContextBetaDescription": "Breidt het contextvenster uit tot 1 miljoen tokens voor Claude Sonnet 4",
"awsBedrock1MContextBetaLabel": "1M contextvenster inschakelen (bèta)",

View file

@ -308,6 +308,9 @@
"anthropicApiKey": "Klucz API Anthropic",
"getAnthropicApiKey": "Uzyskaj klucz API Anthropic",
"anthropicUseAuthToken": "Przekaż klucz API Anthropic jako nagłówek Authorization zamiast X-Api-Key",
"anthropicUseAzureFoundry": "Użyj Azure AI Foundry",
"anthropicAzureDeploymentName": "Nazwa wdrożenia Azure",
"anthropicAzureDeploymentNameDescription": "Wprowadź nazwę wdrożenia Azure Foundry (np. claude-opus-4-5). To zastąpi wybrany identyfikator modelu.",
"anthropic1MContextBetaLabel": "Włącz okno kontekstowe 1M (Beta)",
"anthropic1MContextBetaDescription": "Rozszerza okno kontekstowe do 1 miliona tokenów dla Claude Sonnet 4",
"awsBedrock1MContextBetaLabel": "Włącz okno kontekstowe 1M (Beta)",

View file

@ -308,6 +308,9 @@
"anthropicApiKey": "Chave de API Anthropic",
"getAnthropicApiKey": "Obter chave de API Anthropic",
"anthropicUseAuthToken": "Passar a chave de API Anthropic como cabeçalho Authorization em vez de X-Api-Key",
"anthropicUseAzureFoundry": "Usar Azure AI Foundry",
"anthropicAzureDeploymentName": "Nome da implantação do Azure",
"anthropicAzureDeploymentNameDescription": "Digite o nome da implantação do Azure Foundry (ex: claude-opus-4-5). Isso substituirá o ID do modelo selecionado.",
"anthropic1MContextBetaLabel": "Ativar janela de contexto de 1M (Beta)",
"anthropic1MContextBetaDescription": "Estende a janela de contexto para 1 milhão de tokens para o Claude Sonnet 4",
"awsBedrock1MContextBetaLabel": "Ativar janela de contexto de 1M (Beta)",

View file

@ -308,6 +308,9 @@
"anthropicApiKey": "Anthropic API-ключ",
"getAnthropicApiKey": "Получить Anthropic API-ключ",
"anthropicUseAuthToken": "Передавать Anthropic API-ключ как Authorization-заголовок вместо X-Api-Key",
"anthropicUseAzureFoundry": "Использовать Azure AI Foundry",
"anthropicAzureDeploymentName": "Имя развертывания Azure",
"anthropicAzureDeploymentNameDescription": "Введите имя развертывания Azure Foundry (например, claude-opus-4-5). Это переопределит выбранный ID модели.",
"anthropic1MContextBetaLabel": "Включить контекстное окно 1M (бета)",
"anthropic1MContextBetaDescription": "Расширяет контекстное окно до 1 миллиона токенов для Claude Sonnet 4",
"awsBedrock1MContextBetaLabel": "Включить контекстное окно 1M (бета)",

View file

@ -308,6 +308,9 @@
"anthropicApiKey": "Anthropic API Anahtarı",
"getAnthropicApiKey": "Anthropic API Anahtarı Al",
"anthropicUseAuthToken": "Anthropic API Anahtarını X-Api-Key yerine Authorization başlığı olarak geçir",
"anthropicUseAzureFoundry": "Azure AI Foundry kullan",
"anthropicAzureDeploymentName": "Azure Dağıtım Adı",
"anthropicAzureDeploymentNameDescription": "Azure Foundry dağıtım adınızı girin (örn. claude-opus-4-5). Bu, seçilen model kimliğini geçersiz kılacaktır.",
"anthropic1MContextBetaLabel": "1M bağlam penceresini etkinleştir (Beta)",
"anthropic1MContextBetaDescription": "Claude Sonnet 4 için bağlam penceresini 1 milyon token'a genişletir",
"awsBedrock1MContextBetaLabel": "1M bağlam penceresini etkinleştir (Beta)",

View file

@ -308,6 +308,9 @@
"anthropicApiKey": "Khóa API Anthropic",
"getAnthropicApiKey": "Lấy khóa API Anthropic",
"anthropicUseAuthToken": "Truyền khóa API Anthropic dưới dạng tiêu đề Authorization thay vì X-Api-Key",
"anthropicUseAzureFoundry": "Sử dụng Azure AI Foundry",
"anthropicAzureDeploymentName": "Tên triển khai Azure",
"anthropicAzureDeploymentNameDescription": "Nhập tên triển khai Azure Foundry của bạn (ví dụ: claude-opus-4-5). Điều này sẽ ghi đè ID mô hình đã chọn.",
"anthropic1MContextBetaLabel": "Bật cửa sổ ngữ cảnh 1M (Beta)",
"anthropic1MContextBetaDescription": "Mở rộng cửa sổ ngữ cảnh lên 1 triệu token cho Claude Sonnet 4",
"awsBedrock1MContextBetaLabel": "Bật cửa sổ ngữ cảnh 1M (Beta)",

View file

@ -308,6 +308,9 @@
"anthropicApiKey": "Anthropic API 密钥",
"getAnthropicApiKey": "获取 Anthropic API 密钥",
"anthropicUseAuthToken": "将 Anthropic API 密钥作为 Authorization 标头传递,而不是 X-Api-Key",
"anthropicUseAzureFoundry": "使用 Azure AI Foundry",
"anthropicAzureDeploymentName": "Azure 部署名称",
"anthropicAzureDeploymentNameDescription": "输入您的 Azure Foundry 部署名称(例如 claude-opus-4-5。这将覆盖所选的模型 ID。",
"anthropic1MContextBetaLabel": "启用 1M 上下文窗口 (Beta)",
"anthropic1MContextBetaDescription": "为 Claude Sonnet 4 将上下文窗口扩展至 100 万个 token",
"awsBedrock1MContextBetaLabel": "启用 1M 上下文窗口 (Beta)",

View file

@ -308,6 +308,9 @@
"anthropicApiKey": "Anthropic API 金鑰",
"getAnthropicApiKey": "取得 Anthropic API 金鑰",
"anthropicUseAuthToken": "將 Anthropic API 金鑰作為 Authorization 標頭傳遞,而非使用 X-Api-Key",
"anthropicUseAzureFoundry": "使用 Azure AI Foundry",
"anthropicAzureDeploymentName": "Azure 部署名稱",
"anthropicAzureDeploymentNameDescription": "輸入您的 Azure Foundry 部署名稱(例如 claude-opus-4-5。這將覆蓋所選的模型 ID。",
"anthropic1MContextBetaLabel": "啟用 1M 上下文視窗 (Beta)",
"anthropic1MContextBetaDescription": "為 Claude Sonnet 4 將上下文視窗擴展至 100 萬個 token",
"awsBedrock1MContextBetaLabel": "啟用 1M 上下文視窗 (Beta)",