Browse Source

Add Anthropic option to pass API Token as Authorization header instead of X-Api-Key for the custom base URL (#2531)

Add Anthropic option to use authToken over apiKey
mecab 8 months ago
parent
commit
37cfd75ebf

+ 1 - 0
evals/packages/types/src/roo-code.ts

@@ -301,6 +301,7 @@ export const providerSettingsSchema = z.object({
 	apiModelId: z.string().optional(),
 	apiModelId: z.string().optional(),
 	apiKey: z.string().optional(),
 	apiKey: z.string().optional(),
 	anthropicBaseUrl: z.string().optional(),
 	anthropicBaseUrl: z.string().optional(),
+	anthropicUseAuthToken: z.boolean().optional(),
 	// Glama
 	// Glama
 	glamaModelId: z.string().optional(),
 	glamaModelId: z.string().optional(),
 	glamaModelInfo: modelInfoSchema.optional(),
 	glamaModelInfo: modelInfoSchema.optional(),

+ 37 - 0
src/api/providers/__tests__/anthropic.test.ts

@@ -2,8 +2,10 @@
 
 
 import { AnthropicHandler } from "../anthropic"
 import { AnthropicHandler } from "../anthropic"
 import { ApiHandlerOptions } from "../../../shared/api"
 import { ApiHandlerOptions } from "../../../shared/api"
+import Anthropic from "@anthropic-ai/sdk"
 
 
 const mockCreate = jest.fn()
 const mockCreate = jest.fn()
+const mockAnthropicConstructor = Anthropic.Anthropic as unknown as jest.Mock
 
 
 jest.mock("@anthropic-ai/sdk", () => {
 jest.mock("@anthropic-ai/sdk", () => {
 	return {
 	return {
@@ -69,6 +71,7 @@ describe("AnthropicHandler", () => {
 		}
 		}
 		handler = new AnthropicHandler(mockOptions)
 		handler = new AnthropicHandler(mockOptions)
 		mockCreate.mockClear()
 		mockCreate.mockClear()
+		mockAnthropicConstructor.mockClear()
 	})
 	})
 
 
 	describe("constructor", () => {
 	describe("constructor", () => {
@@ -94,6 +97,40 @@ describe("AnthropicHandler", () => {
 			})
 			})
 			expect(handlerWithCustomUrl).toBeInstanceOf(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", () => {
 	describe("createMessage", () => {

+ 4 - 1
src/api/providers/anthropic.ts

@@ -20,9 +20,12 @@ export class AnthropicHandler extends BaseProvider implements SingleCompletionHa
 	constructor(options: ApiHandlerOptions) {
 	constructor(options: ApiHandlerOptions) {
 		super()
 		super()
 		this.options = options
 		this.options = options
+
+		const apiKeyFieldName =
+			this.options.anthropicBaseUrl && this.options.anthropicUseAuthToken ? "authToken" : "apiKey"
 		this.client = new Anthropic({
 		this.client = new Anthropic({
-			apiKey: this.options.apiKey,
 			baseURL: this.options.anthropicBaseUrl || undefined,
 			baseURL: this.options.anthropicBaseUrl || undefined,
+			[apiKeyFieldName]: this.options.apiKey,
 		})
 		})
 	}
 	}
 
 

+ 1 - 0
src/exports/roo-code.d.ts

@@ -25,6 +25,7 @@ type ProviderSettings = {
 	apiModelId?: string | undefined
 	apiModelId?: string | undefined
 	apiKey?: string | undefined
 	apiKey?: string | undefined
 	anthropicBaseUrl?: string | undefined
 	anthropicBaseUrl?: string | undefined
+	anthropicUseAuthToken?: boolean | undefined
 	glamaModelId?: string | undefined
 	glamaModelId?: string | undefined
 	glamaModelInfo?:
 	glamaModelInfo?:
 		| ({
 		| ({

+ 1 - 0
src/exports/types.ts

@@ -26,6 +26,7 @@ type ProviderSettings = {
 	apiModelId?: string | undefined
 	apiModelId?: string | undefined
 	apiKey?: string | undefined
 	apiKey?: string | undefined
 	anthropicBaseUrl?: string | undefined
 	anthropicBaseUrl?: string | undefined
+	anthropicUseAuthToken?: boolean | undefined
 	glamaModelId?: string | undefined
 	glamaModelId?: string | undefined
 	glamaModelInfo?:
 	glamaModelInfo?:
 		| ({
 		| ({

+ 2 - 0
src/schemas/index.ts

@@ -318,6 +318,7 @@ export const providerSettingsSchema = z.object({
 	apiModelId: z.string().optional(),
 	apiModelId: z.string().optional(),
 	apiKey: z.string().optional(),
 	apiKey: z.string().optional(),
 	anthropicBaseUrl: z.string().optional(),
 	anthropicBaseUrl: z.string().optional(),
+	anthropicUseAuthToken: z.boolean().optional(),
 	// Glama
 	// Glama
 	glamaModelId: z.string().optional(),
 	glamaModelId: z.string().optional(),
 	glamaModelInfo: modelInfoSchema.nullish(),
 	glamaModelInfo: modelInfoSchema.nullish(),
@@ -414,6 +415,7 @@ const providerSettingsRecord: ProviderSettingsRecord = {
 	apiModelId: undefined,
 	apiModelId: undefined,
 	apiKey: undefined,
 	apiKey: undefined,
 	anthropicBaseUrl: undefined,
 	anthropicBaseUrl: undefined,
+	anthropicUseAuthToken: undefined,
 	// Glama
 	// Glama
 	glamaModelId: undefined,
 	glamaModelId: undefined,
 	glamaModelInfo: undefined,
 	glamaModelInfo: undefined,

+ 18 - 7
webview-ui/src/components/settings/ApiOptions.tsx

@@ -414,18 +414,29 @@ const ApiOptions = ({
 
 
 								if (!checked) {
 								if (!checked) {
 									setApiConfigurationField("anthropicBaseUrl", "")
 									setApiConfigurationField("anthropicBaseUrl", "")
+									setApiConfigurationField("anthropicUseAuthToken", false) // added
 								}
 								}
 							}}>
 							}}>
 							{t("settings:providers.useCustomBaseUrl")}
 							{t("settings:providers.useCustomBaseUrl")}
 						</Checkbox>
 						</Checkbox>
 						{anthropicBaseUrlSelected && (
 						{anthropicBaseUrlSelected && (
-							<VSCodeTextField
-								value={apiConfiguration?.anthropicBaseUrl || ""}
-								type="url"
-								onInput={handleInputChange("anthropicBaseUrl")}
-								placeholder="https://api.anthropic.com"
-								className="w-full mt-1"
-							/>
+							<>
+								<VSCodeTextField
+									value={apiConfiguration?.anthropicBaseUrl || ""}
+									type="url"
+									onInput={handleInputChange("anthropicBaseUrl")}
+									placeholder="https://api.anthropic.com"
+									className="w-full mt-1"
+								/>
+
+								{/* added */}
+								<Checkbox
+									checked={apiConfiguration?.anthropicUseAuthToken ?? false}
+									onChange={handleInputChange("anthropicUseAuthToken", noTransform)}
+									className="w-full mt-1">
+									{t("settings:providers.anthropicUseAuthToken")}
+								</Checkbox>
+							</>
 						)}
 						)}
 					</div>
 					</div>
 				</>
 				</>

+ 1 - 0
webview-ui/src/i18n/locales/ca/settings.json

@@ -116,6 +116,7 @@
 		"getRequestyApiKey": "Obtenir clau API de Requesty",
 		"getRequestyApiKey": "Obtenir clau API de Requesty",
 		"anthropicApiKey": "Clau API d'Anthropic",
 		"anthropicApiKey": "Clau API d'Anthropic",
 		"getAnthropicApiKey": "Obtenir 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",
 		"deepSeekApiKey": "Clau API de DeepSeek",
 		"getDeepSeekApiKey": "Obtenir clau API de DeepSeek",
 		"getDeepSeekApiKey": "Obtenir clau API de DeepSeek",
 		"geminiApiKey": "Clau API de Gemini",
 		"geminiApiKey": "Clau API de Gemini",

+ 1 - 0
webview-ui/src/i18n/locales/de/settings.json

@@ -116,6 +116,7 @@
 		"openRouterTransformsText": "Prompts und Nachrichtenketten auf Kontextgröße komprimieren (<a>OpenRouter Transformationen</a>)",
 		"openRouterTransformsText": "Prompts und Nachrichtenketten auf Kontextgröße komprimieren (<a>OpenRouter Transformationen</a>)",
 		"anthropicApiKey": "Anthropic API-Schlüssel",
 		"anthropicApiKey": "Anthropic API-Schlüssel",
 		"getAnthropicApiKey": "Anthropic API-Schlüssel erhalten",
 		"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",
 		"deepSeekApiKey": "DeepSeek API-Schlüssel",
 		"getDeepSeekApiKey": "DeepSeek API-Schlüssel erhalten",
 		"getDeepSeekApiKey": "DeepSeek API-Schlüssel erhalten",
 		"geminiApiKey": "Gemini API-Schlüssel",
 		"geminiApiKey": "Gemini API-Schlüssel",

+ 1 - 0
webview-ui/src/i18n/locales/en/settings.json

@@ -116,6 +116,7 @@
 		"openRouterTransformsText": "Compress prompts and message chains to the context size (<a>OpenRouter Transforms</a>)",
 		"openRouterTransformsText": "Compress prompts and message chains to the context size (<a>OpenRouter Transforms</a>)",
 		"anthropicApiKey": "Anthropic API Key",
 		"anthropicApiKey": "Anthropic API Key",
 		"getAnthropicApiKey": "Get 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",
 		"deepSeekApiKey": "DeepSeek API Key",
 		"getDeepSeekApiKey": "Get DeepSeek API Key",
 		"getDeepSeekApiKey": "Get DeepSeek API Key",
 		"geminiApiKey": "Gemini API Key",
 		"geminiApiKey": "Gemini API Key",

+ 1 - 0
webview-ui/src/i18n/locales/es/settings.json

@@ -116,6 +116,7 @@
 		"openRouterTransformsText": "Comprimir prompts y cadenas de mensajes al tamaño del contexto (<a>Transformaciones de OpenRouter</a>)",
 		"openRouterTransformsText": "Comprimir prompts y cadenas de mensajes al tamaño del contexto (<a>Transformaciones de OpenRouter</a>)",
 		"anthropicApiKey": "Clave API de Anthropic",
 		"anthropicApiKey": "Clave API de Anthropic",
 		"getAnthropicApiKey": "Obtener 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",
 		"deepSeekApiKey": "Clave API de DeepSeek",
 		"getDeepSeekApiKey": "Obtener clave API de DeepSeek",
 		"getDeepSeekApiKey": "Obtener clave API de DeepSeek",
 		"geminiApiKey": "Clave API de Gemini",
 		"geminiApiKey": "Clave API de Gemini",

+ 1 - 0
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 (<a>Transformations OpenRouter</a>)",
 		"openRouterTransformsText": "Compresser les prompts et chaînes de messages à la taille du contexte (<a>Transformations OpenRouter</a>)",
 		"anthropicApiKey": "Clé API Anthropic",
 		"anthropicApiKey": "Clé API Anthropic",
 		"getAnthropicApiKey": "Obtenir la 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",
 		"deepSeekApiKey": "Clé API DeepSeek",
 		"getDeepSeekApiKey": "Obtenir la clé API DeepSeek",
 		"getDeepSeekApiKey": "Obtenir la clé API DeepSeek",
 		"geminiApiKey": "Clé API Gemini",
 		"geminiApiKey": "Clé API Gemini",

+ 1 - 0
webview-ui/src/i18n/locales/hi/settings.json

@@ -116,6 +116,7 @@
 		"openRouterTransformsText": "संदर्भ आकार के लिए प्रॉम्प्ट और संदेश श्रृंखलाओं को संपीड़ित करें (<a>OpenRouter ट्रांसफॉर्म</a>)",
 		"openRouterTransformsText": "संदर्भ आकार के लिए प्रॉम्प्ट और संदेश श्रृंखलाओं को संपीड़ित करें (<a>OpenRouter ट्रांसफॉर्म</a>)",
 		"anthropicApiKey": "Anthropic API कुंजी",
 		"anthropicApiKey": "Anthropic API कुंजी",
 		"getAnthropicApiKey": "Anthropic API कुंजी प्राप्त करें",
 		"getAnthropicApiKey": "Anthropic API कुंजी प्राप्त करें",
+		"anthropicUseAuthToken": "X-Api-Key के बजाय Anthropic API कुंजी को Authorization हेडर के रूप में पास करें",
 		"deepSeekApiKey": "DeepSeek API कुंजी",
 		"deepSeekApiKey": "DeepSeek API कुंजी",
 		"getDeepSeekApiKey": "DeepSeek API कुंजी प्राप्त करें",
 		"getDeepSeekApiKey": "DeepSeek API कुंजी प्राप्त करें",
 		"geminiApiKey": "Gemini API कुंजी",
 		"geminiApiKey": "Gemini API कुंजी",

+ 1 - 0
webview-ui/src/i18n/locales/it/settings.json

@@ -116,6 +116,7 @@
 		"openRouterTransformsText": "Comprimi prompt e catene di messaggi alla dimensione del contesto (<a>Trasformazioni OpenRouter</a>)",
 		"openRouterTransformsText": "Comprimi prompt e catene di messaggi alla dimensione del contesto (<a>Trasformazioni OpenRouter</a>)",
 		"anthropicApiKey": "Chiave API Anthropic",
 		"anthropicApiKey": "Chiave API Anthropic",
 		"getAnthropicApiKey": "Ottieni 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",
 		"deepSeekApiKey": "Chiave API DeepSeek",
 		"getDeepSeekApiKey": "Ottieni chiave API DeepSeek",
 		"getDeepSeekApiKey": "Ottieni chiave API DeepSeek",
 		"geminiApiKey": "Chiave API Gemini",
 		"geminiApiKey": "Chiave API Gemini",

+ 1 - 0
webview-ui/src/i18n/locales/ja/settings.json

@@ -116,6 +116,7 @@
 		"openRouterTransformsText": "プロンプトとメッセージチェーンをコンテキストサイズに圧縮 (<a>OpenRouter Transforms</a>)",
 		"openRouterTransformsText": "プロンプトとメッセージチェーンをコンテキストサイズに圧縮 (<a>OpenRouter Transforms</a>)",
 		"anthropicApiKey": "Anthropic APIキー",
 		"anthropicApiKey": "Anthropic APIキー",
 		"getAnthropicApiKey": "Anthropic APIキーを取得",
 		"getAnthropicApiKey": "Anthropic APIキーを取得",
+		"anthropicUseAuthToken": "Anthropic APIキーをX-Api-Keyの代わりにAuthorizationヘッダーとして渡す",
 		"deepSeekApiKey": "DeepSeek APIキー",
 		"deepSeekApiKey": "DeepSeek APIキー",
 		"getDeepSeekApiKey": "DeepSeek APIキーを取得",
 		"getDeepSeekApiKey": "DeepSeek APIキーを取得",
 		"geminiApiKey": "Gemini APIキー",
 		"geminiApiKey": "Gemini APIキー",

+ 1 - 0
webview-ui/src/i18n/locales/ko/settings.json

@@ -116,6 +116,7 @@
 		"openRouterTransformsText": "프롬프트와 메시지 체인을 컨텍스트 크기로 압축 (<a>OpenRouter Transforms</a>)",
 		"openRouterTransformsText": "프롬프트와 메시지 체인을 컨텍스트 크기로 압축 (<a>OpenRouter Transforms</a>)",
 		"anthropicApiKey": "Anthropic API 키",
 		"anthropicApiKey": "Anthropic API 키",
 		"getAnthropicApiKey": "Anthropic API 키 받기",
 		"getAnthropicApiKey": "Anthropic API 키 받기",
+		"anthropicUseAuthToken": "X-Api-Key 대신 Authorization 헤더로 Anthropic API 키 전달",
 		"deepSeekApiKey": "DeepSeek API 키",
 		"deepSeekApiKey": "DeepSeek API 키",
 		"getDeepSeekApiKey": "DeepSeek API 키 받기",
 		"getDeepSeekApiKey": "DeepSeek API 키 받기",
 		"geminiApiKey": "Gemini API 키",
 		"geminiApiKey": "Gemini API 키",

+ 1 - 0
webview-ui/src/i18n/locales/pl/settings.json

@@ -116,6 +116,7 @@
 		"openRouterTransformsText": "Kompresuj podpowiedzi i łańcuchy wiadomości do rozmiaru kontekstu (<a>Transformacje OpenRouter</a>)",
 		"openRouterTransformsText": "Kompresuj podpowiedzi i łańcuchy wiadomości do rozmiaru kontekstu (<a>Transformacje OpenRouter</a>)",
 		"anthropicApiKey": "Klucz API Anthropic",
 		"anthropicApiKey": "Klucz API Anthropic",
 		"getAnthropicApiKey": "Uzyskaj 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",
 		"deepSeekApiKey": "Klucz API DeepSeek",
 		"getDeepSeekApiKey": "Uzyskaj klucz API DeepSeek",
 		"getDeepSeekApiKey": "Uzyskaj klucz API DeepSeek",
 		"geminiApiKey": "Klucz API Gemini",
 		"geminiApiKey": "Klucz API Gemini",

+ 1 - 0
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 (<a>Transformações OpenRouter</a>)",
 		"openRouterTransformsText": "Comprimir prompts e cadeias de mensagens para o tamanho do contexto (<a>Transformações OpenRouter</a>)",
 		"anthropicApiKey": "Chave de API Anthropic",
 		"anthropicApiKey": "Chave de API Anthropic",
 		"getAnthropicApiKey": "Obter 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",
 		"deepSeekApiKey": "Chave de API DeepSeek",
 		"getDeepSeekApiKey": "Obter chave de API DeepSeek",
 		"getDeepSeekApiKey": "Obter chave de API DeepSeek",
 		"geminiApiKey": "Chave de API Gemini",
 		"geminiApiKey": "Chave de API Gemini",

+ 1 - 0
webview-ui/src/i18n/locales/tr/settings.json

@@ -116,6 +116,7 @@
 		"openRouterTransformsText": "İstem ve mesaj zincirlerini bağlam boyutuna sıkıştır (<a>OpenRouter Dönüşümleri</a>)",
 		"openRouterTransformsText": "İstem ve mesaj zincirlerini bağlam boyutuna sıkıştır (<a>OpenRouter Dönüşümleri</a>)",
 		"anthropicApiKey": "Anthropic API Anahtarı",
 		"anthropicApiKey": "Anthropic API Anahtarı",
 		"getAnthropicApiKey": "Anthropic API Anahtarı Al",
 		"getAnthropicApiKey": "Anthropic API Anahtarı Al",
+		"anthropicUseAuthToken": "Anthropic API Anahtarını X-Api-Key yerine Authorization başlığı olarak geçir",
 		"deepSeekApiKey": "DeepSeek API Anahtarı",
 		"deepSeekApiKey": "DeepSeek API Anahtarı",
 		"getDeepSeekApiKey": "DeepSeek API Anahtarı Al",
 		"getDeepSeekApiKey": "DeepSeek API Anahtarı Al",
 		"geminiApiKey": "Gemini API Anahtarı",
 		"geminiApiKey": "Gemini API Anahtarı",

+ 1 - 0
webview-ui/src/i18n/locales/vi/settings.json

@@ -115,6 +115,7 @@
 		"getRequestyApiKey": "Lấy khóa API Requesty",
 		"getRequestyApiKey": "Lấy khóa API Requesty",
 		"anthropicApiKey": "Khóa API Anthropic",
 		"anthropicApiKey": "Khóa API Anthropic",
 		"getAnthropicApiKey": "Lấy 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",
 		"deepSeekApiKey": "Khóa API DeepSeek",
 		"getDeepSeekApiKey": "Lấy khóa API DeepSeek",
 		"getDeepSeekApiKey": "Lấy khóa API DeepSeek",
 		"geminiApiKey": "Khóa API Gemini",
 		"geminiApiKey": "Khóa API Gemini",

+ 1 - 0
webview-ui/src/i18n/locales/zh-CN/settings.json

@@ -116,6 +116,7 @@
 		"openRouterTransformsText": "自动压缩提示词和消息链到上下文长度限制内 (<a>OpenRouter转换</a>)",
 		"openRouterTransformsText": "自动压缩提示词和消息链到上下文长度限制内 (<a>OpenRouter转换</a>)",
 		"anthropicApiKey": "Anthropic API 密钥",
 		"anthropicApiKey": "Anthropic API 密钥",
 		"getAnthropicApiKey": "获取 Anthropic API 密钥",
 		"getAnthropicApiKey": "获取 Anthropic API 密钥",
+		"anthropicUseAuthToken": "将 Anthropic API 密钥作为 Authorization 标头传递,而不是 X-Api-Key",
 		"deepSeekApiKey": "DeepSeek API 密钥",
 		"deepSeekApiKey": "DeepSeek API 密钥",
 		"getDeepSeekApiKey": "获取 DeepSeek API 密钥",
 		"getDeepSeekApiKey": "获取 DeepSeek API 密钥",
 		"geminiApiKey": "Gemini API 密钥",
 		"geminiApiKey": "Gemini API 密钥",

+ 1 - 0
webview-ui/src/i18n/locales/zh-TW/settings.json

@@ -116,6 +116,7 @@
 		"openRouterTransformsText": "將提示和訊息鏈壓縮到上下文大小 (<a>OpenRouter 轉換</a>)",
 		"openRouterTransformsText": "將提示和訊息鏈壓縮到上下文大小 (<a>OpenRouter 轉換</a>)",
 		"anthropicApiKey": "Anthropic API 金鑰",
 		"anthropicApiKey": "Anthropic API 金鑰",
 		"getAnthropicApiKey": "取得 Anthropic API 金鑰",
 		"getAnthropicApiKey": "取得 Anthropic API 金鑰",
+		"anthropicUseAuthToken": "將 Anthropic API 金鑰作為 Authorization 標頭傳遞,而非使用 X-Api-Key",
 		"deepSeekApiKey": "DeepSeek API 金鑰",
 		"deepSeekApiKey": "DeepSeek API 金鑰",
 		"getDeepSeekApiKey": "取得 DeepSeek API 金鑰",
 		"getDeepSeekApiKey": "取得 DeepSeek API 金鑰",
 		"geminiApiKey": "Gemini API 金鑰",
 		"geminiApiKey": "Gemini API 金鑰",