diff --git a/evals/packages/types/src/roo-code.ts b/evals/packages/types/src/roo-code.ts
index 9462b7aa754..5a4082395b8 100644
--- a/evals/packages/types/src/roo-code.ts
+++ b/evals/packages/types/src/roo-code.ts
@@ -301,6 +301,7 @@ export const providerSettingsSchema = z.object({
apiModelId: z.string().optional(),
apiKey: z.string().optional(),
anthropicBaseUrl: z.string().optional(),
+ anthropicUseAuthToken: z.boolean().optional(),
// Glama
glamaModelId: z.string().optional(),
glamaModelInfo: modelInfoSchema.optional(),
diff --git a/src/api/providers/__tests__/anthropic.test.ts b/src/api/providers/__tests__/anthropic.test.ts
index fe367ea674f..fe186e3d8fa 100644
--- a/src/api/providers/__tests__/anthropic.test.ts
+++ b/src/api/providers/__tests__/anthropic.test.ts
@@ -2,8 +2,10 @@
import { AnthropicHandler } from "../anthropic"
import { ApiHandlerOptions } from "../../../shared/api"
+import Anthropic from "@anthropic-ai/sdk"
const mockCreate = jest.fn()
+const mockAnthropicConstructor = Anthropic.Anthropic as unknown as jest.Mock
jest.mock("@anthropic-ai/sdk", () => {
return {
@@ -69,6 +71,7 @@ describe("AnthropicHandler", () => {
}
handler = new AnthropicHandler(mockOptions)
mockCreate.mockClear()
+ mockAnthropicConstructor.mockClear()
})
describe("constructor", () => {
@@ -94,6 +97,40 @@ describe("AnthropicHandler", () => {
})
expect(handlerWithCustomUrl).toBeInstanceOf(AnthropicHandler)
})
+
+ it("use apiKey for passing token if anthropicUseAuthToken is not set", () => {
+ const handlerWithCustomUrl = new AnthropicHandler({
+ ...mockOptions,
+ })
+ expect(handlerWithCustomUrl).toBeInstanceOf(AnthropicHandler)
+ expect(mockAnthropicConstructor).toHaveBeenCalledTimes(1)
+ expect(mockAnthropicConstructor.mock.lastCall[0].apiKey).toEqual("test-api-key")
+ expect(mockAnthropicConstructor.mock.lastCall[0].authToken).toBeUndefined()
+ })
+
+ it("use apiKey for passing token if anthropicUseAuthToken is set but custom base URL is not given", () => {
+ const handlerWithCustomUrl = new AnthropicHandler({
+ ...mockOptions,
+ anthropicUseAuthToken: true,
+ })
+ expect(handlerWithCustomUrl).toBeInstanceOf(AnthropicHandler)
+ expect(mockAnthropicConstructor).toHaveBeenCalledTimes(1)
+ expect(mockAnthropicConstructor.mock.lastCall[0].apiKey).toEqual("test-api-key")
+ expect(mockAnthropicConstructor.mock.lastCall[0].authToken).toBeUndefined()
+ })
+
+ it("use authToken for passing token if both of anthropicBaseUrl and anthropicUseAuthToken are set", () => {
+ const customBaseUrl = "https://custom.anthropic.com"
+ const handlerWithCustomUrl = new AnthropicHandler({
+ ...mockOptions,
+ anthropicBaseUrl: customBaseUrl,
+ anthropicUseAuthToken: true,
+ })
+ expect(handlerWithCustomUrl).toBeInstanceOf(AnthropicHandler)
+ expect(mockAnthropicConstructor).toHaveBeenCalledTimes(1)
+ expect(mockAnthropicConstructor.mock.lastCall[0].authToken).toEqual("test-api-key")
+ expect(mockAnthropicConstructor.mock.lastCall[0].apiKey).toBeUndefined()
+ })
})
describe("createMessage", () => {
diff --git a/src/api/providers/anthropic.ts b/src/api/providers/anthropic.ts
index 681ef2fc77c..a906ad6e7ef 100644
--- a/src/api/providers/anthropic.ts
+++ b/src/api/providers/anthropic.ts
@@ -20,9 +20,12 @@ export class AnthropicHandler extends BaseProvider implements SingleCompletionHa
constructor(options: ApiHandlerOptions) {
super()
this.options = options
+
+ const apiKeyFieldName =
+ this.options.anthropicBaseUrl && this.options.anthropicUseAuthToken ? "authToken" : "apiKey"
this.client = new Anthropic({
- apiKey: this.options.apiKey,
baseURL: this.options.anthropicBaseUrl || undefined,
+ [apiKeyFieldName]: this.options.apiKey,
})
}
diff --git a/src/exports/roo-code.d.ts b/src/exports/roo-code.d.ts
index e137b4c4822..b337e81fa2a 100644
--- a/src/exports/roo-code.d.ts
+++ b/src/exports/roo-code.d.ts
@@ -25,6 +25,7 @@ type ProviderSettings = {
apiModelId?: string | undefined
apiKey?: string | undefined
anthropicBaseUrl?: string | undefined
+ anthropicUseAuthToken?: boolean | undefined
glamaModelId?: string | undefined
glamaModelInfo?:
| ({
diff --git a/src/exports/types.ts b/src/exports/types.ts
index 8fa340f719e..05a70d133b5 100644
--- a/src/exports/types.ts
+++ b/src/exports/types.ts
@@ -26,6 +26,7 @@ type ProviderSettings = {
apiModelId?: string | undefined
apiKey?: string | undefined
anthropicBaseUrl?: string | undefined
+ anthropicUseAuthToken?: boolean | undefined
glamaModelId?: string | undefined
glamaModelInfo?:
| ({
diff --git a/src/schemas/index.ts b/src/schemas/index.ts
index 64eec0bf644..a73152773c1 100644
--- a/src/schemas/index.ts
+++ b/src/schemas/index.ts
@@ -318,6 +318,7 @@ export const providerSettingsSchema = z.object({
apiModelId: z.string().optional(),
apiKey: z.string().optional(),
anthropicBaseUrl: z.string().optional(),
+ anthropicUseAuthToken: z.boolean().optional(),
// Glama
glamaModelId: z.string().optional(),
glamaModelInfo: modelInfoSchema.nullish(),
@@ -414,6 +415,7 @@ const providerSettingsRecord: ProviderSettingsRecord = {
apiModelId: undefined,
apiKey: undefined,
anthropicBaseUrl: undefined,
+ anthropicUseAuthToken: undefined,
// Glama
glamaModelId: undefined,
glamaModelInfo: undefined,
diff --git a/webview-ui/src/components/settings/ApiOptions.tsx b/webview-ui/src/components/settings/ApiOptions.tsx
index 55690d48069..cfc48e8f73f 100644
--- a/webview-ui/src/components/settings/ApiOptions.tsx
+++ b/webview-ui/src/components/settings/ApiOptions.tsx
@@ -414,18 +414,29 @@ const ApiOptions = ({
if (!checked) {
setApiConfigurationField("anthropicBaseUrl", "")
+ setApiConfigurationField("anthropicUseAuthToken", false) // added
}
}}>
{t("settings:providers.useCustomBaseUrl")}
{anthropicBaseUrlSelected && (
-
+ <>
+
+
+ {/* added */}
+
+ {t("settings:providers.anthropicUseAuthToken")}
+
+ >
)}
>
diff --git a/webview-ui/src/i18n/locales/ca/settings.json b/webview-ui/src/i18n/locales/ca/settings.json
index 390362f099b..80b3ef3a48f 100644
--- a/webview-ui/src/i18n/locales/ca/settings.json
+++ b/webview-ui/src/i18n/locales/ca/settings.json
@@ -116,6 +116,7 @@
"getRequestyApiKey": "Obtenir clau API de Requesty",
"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",
"deepSeekApiKey": "Clau API de DeepSeek",
"getDeepSeekApiKey": "Obtenir clau API de DeepSeek",
"geminiApiKey": "Clau API de Gemini",
diff --git a/webview-ui/src/i18n/locales/de/settings.json b/webview-ui/src/i18n/locales/de/settings.json
index 59ea1f6f1ea..a577199e866 100644
--- a/webview-ui/src/i18n/locales/de/settings.json
+++ b/webview-ui/src/i18n/locales/de/settings.json
@@ -116,6 +116,7 @@
"openRouterTransformsText": "Prompts und Nachrichtenketten auf Kontextgröße komprimieren (OpenRouter Transformationen)",
"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",
"deepSeekApiKey": "DeepSeek API-Schlüssel",
"getDeepSeekApiKey": "DeepSeek API-Schlüssel erhalten",
"geminiApiKey": "Gemini API-Schlüssel",
diff --git a/webview-ui/src/i18n/locales/en/settings.json b/webview-ui/src/i18n/locales/en/settings.json
index 5ba66f34e27..9d2b6f89204 100644
--- a/webview-ui/src/i18n/locales/en/settings.json
+++ b/webview-ui/src/i18n/locales/en/settings.json
@@ -116,6 +116,7 @@
"openRouterTransformsText": "Compress prompts and message chains to the context size (OpenRouter Transforms)",
"anthropicApiKey": "Anthropic API Key",
"getAnthropicApiKey": "Get Anthropic API Key",
+ "anthropicUseAuthToken": "Pass Anthropic API Key as Authorization header instead of X-Api-Key",
"deepSeekApiKey": "DeepSeek API Key",
"getDeepSeekApiKey": "Get DeepSeek API Key",
"geminiApiKey": "Gemini API Key",
diff --git a/webview-ui/src/i18n/locales/es/settings.json b/webview-ui/src/i18n/locales/es/settings.json
index 256c4d73f3b..4b29147b59a 100644
--- a/webview-ui/src/i18n/locales/es/settings.json
+++ b/webview-ui/src/i18n/locales/es/settings.json
@@ -116,6 +116,7 @@
"openRouterTransformsText": "Comprimir prompts y cadenas de mensajes al tamaño del contexto (Transformaciones de OpenRouter)",
"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",
"deepSeekApiKey": "Clave API de DeepSeek",
"getDeepSeekApiKey": "Obtener clave API de DeepSeek",
"geminiApiKey": "Clave API de Gemini",
diff --git a/webview-ui/src/i18n/locales/fr/settings.json b/webview-ui/src/i18n/locales/fr/settings.json
index 23d99a057d4..5a064411b69 100644
--- a/webview-ui/src/i18n/locales/fr/settings.json
+++ b/webview-ui/src/i18n/locales/fr/settings.json
@@ -116,6 +116,7 @@
"openRouterTransformsText": "Compresser les prompts et chaînes de messages à la taille du contexte (Transformations OpenRouter)",
"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",
"deepSeekApiKey": "Clé API DeepSeek",
"getDeepSeekApiKey": "Obtenir la clé API DeepSeek",
"geminiApiKey": "Clé API Gemini",
diff --git a/webview-ui/src/i18n/locales/hi/settings.json b/webview-ui/src/i18n/locales/hi/settings.json
index 59556718c11..d8bf7cd72e3 100644
--- a/webview-ui/src/i18n/locales/hi/settings.json
+++ b/webview-ui/src/i18n/locales/hi/settings.json
@@ -116,6 +116,7 @@
"openRouterTransformsText": "संदर्भ आकार के लिए प्रॉम्प्ट और संदेश श्रृंखलाओं को संपीड़ित करें (OpenRouter ट्रांसफॉर्म)",
"anthropicApiKey": "Anthropic API कुंजी",
"getAnthropicApiKey": "Anthropic API कुंजी प्राप्त करें",
+ "anthropicUseAuthToken": "X-Api-Key के बजाय Anthropic API कुंजी को Authorization हेडर के रूप में पास करें",
"deepSeekApiKey": "DeepSeek API कुंजी",
"getDeepSeekApiKey": "DeepSeek API कुंजी प्राप्त करें",
"geminiApiKey": "Gemini API कुंजी",
diff --git a/webview-ui/src/i18n/locales/it/settings.json b/webview-ui/src/i18n/locales/it/settings.json
index 30340b5e29a..fb2edd63c97 100644
--- a/webview-ui/src/i18n/locales/it/settings.json
+++ b/webview-ui/src/i18n/locales/it/settings.json
@@ -116,6 +116,7 @@
"openRouterTransformsText": "Comprimi prompt e catene di messaggi alla dimensione del contesto (Trasformazioni OpenRouter)",
"anthropicApiKey": "Chiave API Anthropic",
"getAnthropicApiKey": "Ottieni chiave API Anthropic",
+ "anthropicUseAuthToken": "Passa la chiave API Anthropic come header di autorizzazione invece di X-Api-Key",
"deepSeekApiKey": "Chiave API DeepSeek",
"getDeepSeekApiKey": "Ottieni chiave API DeepSeek",
"geminiApiKey": "Chiave API Gemini",
diff --git a/webview-ui/src/i18n/locales/ja/settings.json b/webview-ui/src/i18n/locales/ja/settings.json
index 03e2838d091..aa5b8935292 100644
--- a/webview-ui/src/i18n/locales/ja/settings.json
+++ b/webview-ui/src/i18n/locales/ja/settings.json
@@ -116,6 +116,7 @@
"openRouterTransformsText": "プロンプトとメッセージチェーンをコンテキストサイズに圧縮 (OpenRouter Transforms)",
"anthropicApiKey": "Anthropic APIキー",
"getAnthropicApiKey": "Anthropic APIキーを取得",
+ "anthropicUseAuthToken": "Anthropic APIキーをX-Api-Keyの代わりにAuthorizationヘッダーとして渡す",
"deepSeekApiKey": "DeepSeek APIキー",
"getDeepSeekApiKey": "DeepSeek APIキーを取得",
"geminiApiKey": "Gemini APIキー",
diff --git a/webview-ui/src/i18n/locales/ko/settings.json b/webview-ui/src/i18n/locales/ko/settings.json
index b31df80304e..49e253360b2 100644
--- a/webview-ui/src/i18n/locales/ko/settings.json
+++ b/webview-ui/src/i18n/locales/ko/settings.json
@@ -116,6 +116,7 @@
"openRouterTransformsText": "프롬프트와 메시지 체인을 컨텍스트 크기로 압축 (OpenRouter Transforms)",
"anthropicApiKey": "Anthropic API 키",
"getAnthropicApiKey": "Anthropic API 키 받기",
+ "anthropicUseAuthToken": "X-Api-Key 대신 Authorization 헤더로 Anthropic API 키 전달",
"deepSeekApiKey": "DeepSeek API 키",
"getDeepSeekApiKey": "DeepSeek API 키 받기",
"geminiApiKey": "Gemini API 키",
diff --git a/webview-ui/src/i18n/locales/pl/settings.json b/webview-ui/src/i18n/locales/pl/settings.json
index 7f12e21360a..9b70bb1dc66 100644
--- a/webview-ui/src/i18n/locales/pl/settings.json
+++ b/webview-ui/src/i18n/locales/pl/settings.json
@@ -116,6 +116,7 @@
"openRouterTransformsText": "Kompresuj podpowiedzi i łańcuchy wiadomości do rozmiaru kontekstu (Transformacje OpenRouter)",
"anthropicApiKey": "Klucz API Anthropic",
"getAnthropicApiKey": "Uzyskaj klucz API Anthropic",
+ "anthropicUseAuthToken": "Przekaż klucz API Anthropic jako nagłówek Authorization zamiast X-Api-Key",
"deepSeekApiKey": "Klucz API DeepSeek",
"getDeepSeekApiKey": "Uzyskaj klucz API DeepSeek",
"geminiApiKey": "Klucz API Gemini",
diff --git a/webview-ui/src/i18n/locales/pt-BR/settings.json b/webview-ui/src/i18n/locales/pt-BR/settings.json
index c19a832a57d..3f238e2b37d 100644
--- a/webview-ui/src/i18n/locales/pt-BR/settings.json
+++ b/webview-ui/src/i18n/locales/pt-BR/settings.json
@@ -116,6 +116,7 @@
"openRouterTransformsText": "Comprimir prompts e cadeias de mensagens para o tamanho do contexto (Transformações OpenRouter)",
"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",
"deepSeekApiKey": "Chave de API DeepSeek",
"getDeepSeekApiKey": "Obter chave de API DeepSeek",
"geminiApiKey": "Chave de API Gemini",
diff --git a/webview-ui/src/i18n/locales/tr/settings.json b/webview-ui/src/i18n/locales/tr/settings.json
index 9ad9fedc880..4e2f5b816a3 100644
--- a/webview-ui/src/i18n/locales/tr/settings.json
+++ b/webview-ui/src/i18n/locales/tr/settings.json
@@ -116,6 +116,7 @@
"openRouterTransformsText": "İstem ve mesaj zincirlerini bağlam boyutuna sıkıştır (OpenRouter Dönüşümleri)",
"anthropicApiKey": "Anthropic API Anahtarı",
"getAnthropicApiKey": "Anthropic API Anahtarı Al",
+ "anthropicUseAuthToken": "Anthropic API Anahtarını X-Api-Key yerine Authorization başlığı olarak geçir",
"deepSeekApiKey": "DeepSeek API Anahtarı",
"getDeepSeekApiKey": "DeepSeek API Anahtarı Al",
"geminiApiKey": "Gemini API Anahtarı",
diff --git a/webview-ui/src/i18n/locales/vi/settings.json b/webview-ui/src/i18n/locales/vi/settings.json
index 24eb91d4a2e..0b83f89634e 100644
--- a/webview-ui/src/i18n/locales/vi/settings.json
+++ b/webview-ui/src/i18n/locales/vi/settings.json
@@ -115,6 +115,7 @@
"getRequestyApiKey": "Lấy khóa API Requesty",
"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",
"deepSeekApiKey": "Khóa API DeepSeek",
"getDeepSeekApiKey": "Lấy khóa API DeepSeek",
"geminiApiKey": "Khóa API Gemini",
diff --git a/webview-ui/src/i18n/locales/zh-CN/settings.json b/webview-ui/src/i18n/locales/zh-CN/settings.json
index fd1919a5c31..e995e0101f2 100644
--- a/webview-ui/src/i18n/locales/zh-CN/settings.json
+++ b/webview-ui/src/i18n/locales/zh-CN/settings.json
@@ -116,6 +116,7 @@
"openRouterTransformsText": "自动压缩提示词和消息链到上下文长度限制内 (OpenRouter转换)",
"anthropicApiKey": "Anthropic API 密钥",
"getAnthropicApiKey": "获取 Anthropic API 密钥",
+ "anthropicUseAuthToken": "将 Anthropic API 密钥作为 Authorization 标头传递,而不是 X-Api-Key",
"deepSeekApiKey": "DeepSeek API 密钥",
"getDeepSeekApiKey": "获取 DeepSeek API 密钥",
"geminiApiKey": "Gemini API 密钥",
diff --git a/webview-ui/src/i18n/locales/zh-TW/settings.json b/webview-ui/src/i18n/locales/zh-TW/settings.json
index baa4b614d86..23a0b3ba5c1 100644
--- a/webview-ui/src/i18n/locales/zh-TW/settings.json
+++ b/webview-ui/src/i18n/locales/zh-TW/settings.json
@@ -116,6 +116,7 @@
"openRouterTransformsText": "將提示和訊息鏈壓縮到上下文大小 (OpenRouter 轉換)",
"anthropicApiKey": "Anthropic API 金鑰",
"getAnthropicApiKey": "取得 Anthropic API 金鑰",
+ "anthropicUseAuthToken": "將 Anthropic API 金鑰作為 Authorization 標頭傳遞,而非使用 X-Api-Key",
"deepSeekApiKey": "DeepSeek API 金鑰",
"getDeepSeekApiKey": "取得 DeepSeek API 金鑰",
"geminiApiKey": "Gemini API 金鑰",