Skip to content

Commit 494b98d

Browse files
committed
Add Anthropic option to use authToken over apiKey
1 parent 2c8304e commit 494b98d

File tree

22 files changed

+79
-8
lines changed

22 files changed

+79
-8
lines changed

evals/packages/types/src/roo-code.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -301,6 +301,7 @@ export const providerSettingsSchema = z.object({
301301
apiModelId: z.string().optional(),
302302
apiKey: z.string().optional(),
303303
anthropicBaseUrl: z.string().optional(),
304+
anthropicUseAuthToken: z.boolean().optional(),
304305
// Glama
305306
glamaModelId: z.string().optional(),
306307
glamaModelInfo: modelInfoSchema.optional(),

src/api/providers/__tests__/anthropic.test.ts

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,10 @@
22

33
import { AnthropicHandler } from "../anthropic"
44
import { ApiHandlerOptions } from "../../../shared/api"
5+
import Anthropic from "@anthropic-ai/sdk"
56

67
const mockCreate = jest.fn()
8+
const mockAnthropicConstructor = Anthropic.Anthropic as unknown as jest.Mock
79

810
jest.mock("@anthropic-ai/sdk", () => {
911
return {
@@ -69,6 +71,7 @@ describe("AnthropicHandler", () => {
6971
}
7072
handler = new AnthropicHandler(mockOptions)
7173
mockCreate.mockClear()
74+
mockAnthropicConstructor.mockClear()
7275
})
7376

7477
describe("constructor", () => {
@@ -94,6 +97,40 @@ describe("AnthropicHandler", () => {
9497
})
9598
expect(handlerWithCustomUrl).toBeInstanceOf(AnthropicHandler)
9699
})
100+
101+
it("use apiKey for passing token if anthropicUseAuthToken is not set", () => {
102+
const handlerWithCustomUrl = new AnthropicHandler({
103+
...mockOptions,
104+
})
105+
expect(handlerWithCustomUrl).toBeInstanceOf(AnthropicHandler)
106+
expect(mockAnthropicConstructor).toHaveBeenCalledTimes(1)
107+
expect(mockAnthropicConstructor.mock.lastCall[0].apiKey).toEqual("test-api-key")
108+
expect(mockAnthropicConstructor.mock.lastCall[0].authToken).toBeUndefined()
109+
})
110+
111+
it("use apiKey for passing token if anthropicUseAuthToken is set but custom base URL is not given", () => {
112+
const handlerWithCustomUrl = new AnthropicHandler({
113+
...mockOptions,
114+
anthropicUseAuthToken: true,
115+
})
116+
expect(handlerWithCustomUrl).toBeInstanceOf(AnthropicHandler)
117+
expect(mockAnthropicConstructor).toHaveBeenCalledTimes(1)
118+
expect(mockAnthropicConstructor.mock.lastCall[0].apiKey).toEqual("test-api-key")
119+
expect(mockAnthropicConstructor.mock.lastCall[0].authToken).toBeUndefined()
120+
})
121+
122+
it("use authToken for passing token if both of anthropicBaseUrl and anthropicUseAuthToken are set", () => {
123+
const customBaseUrl = "https://custom.anthropic.com"
124+
const handlerWithCustomUrl = new AnthropicHandler({
125+
...mockOptions,
126+
anthropicBaseUrl: customBaseUrl,
127+
anthropicUseAuthToken: true,
128+
})
129+
expect(handlerWithCustomUrl).toBeInstanceOf(AnthropicHandler)
130+
expect(mockAnthropicConstructor).toHaveBeenCalledTimes(1)
131+
expect(mockAnthropicConstructor.mock.lastCall[0].authToken).toEqual("test-api-key")
132+
expect(mockAnthropicConstructor.mock.lastCall[0].apiKey).toBeUndefined()
133+
})
97134
})
98135

99136
describe("createMessage", () => {

src/api/providers/anthropic.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,12 @@ export class AnthropicHandler extends BaseProvider implements SingleCompletionHa
2020
constructor(options: ApiHandlerOptions) {
2121
super()
2222
this.options = options
23+
24+
const apiKeyFieldName =
25+
this.options.anthropicBaseUrl && this.options.anthropicUseAuthToken ? "authToken" : "apiKey"
2326
this.client = new Anthropic({
24-
apiKey: this.options.apiKey,
2527
baseURL: this.options.anthropicBaseUrl || undefined,
28+
[apiKeyFieldName]: this.options.apiKey,
2629
})
2730
}
2831

src/exports/roo-code.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ type ProviderSettings = {
2525
apiModelId?: string | undefined
2626
apiKey?: string | undefined
2727
anthropicBaseUrl?: string | undefined
28+
anthropicUseAuthToken?: boolean | undefined
2829
glamaModelId?: string | undefined
2930
glamaModelInfo?:
3031
| ({

src/exports/types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ type ProviderSettings = {
2626
apiModelId?: string | undefined
2727
apiKey?: string | undefined
2828
anthropicBaseUrl?: string | undefined
29+
anthropicUseAuthToken?: boolean | undefined
2930
glamaModelId?: string | undefined
3031
glamaModelInfo?:
3132
| ({

src/schemas/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -318,6 +318,7 @@ export const providerSettingsSchema = z.object({
318318
apiModelId: z.string().optional(),
319319
apiKey: z.string().optional(),
320320
anthropicBaseUrl: z.string().optional(),
321+
anthropicUseAuthToken: z.boolean().optional(),
321322
// Glama
322323
glamaModelId: z.string().optional(),
323324
glamaModelInfo: modelInfoSchema.nullish(),
@@ -414,6 +415,7 @@ const providerSettingsRecord: ProviderSettingsRecord = {
414415
apiModelId: undefined,
415416
apiKey: undefined,
416417
anthropicBaseUrl: undefined,
418+
anthropicUseAuthToken: undefined,
417419
// Glama
418420
glamaModelId: undefined,
419421
glamaModelInfo: undefined,

webview-ui/src/components/settings/ApiOptions.tsx

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -414,18 +414,29 @@ const ApiOptions = ({
414414

415415
if (!checked) {
416416
setApiConfigurationField("anthropicBaseUrl", "")
417+
setApiConfigurationField("anthropicUseAuthToken", false) // added
417418
}
418419
}}>
419420
{t("settings:providers.useCustomBaseUrl")}
420421
</Checkbox>
421422
{anthropicBaseUrlSelected && (
422-
<VSCodeTextField
423-
value={apiConfiguration?.anthropicBaseUrl || ""}
424-
type="url"
425-
onInput={handleInputChange("anthropicBaseUrl")}
426-
placeholder="https://api.anthropic.com"
427-
className="w-full mt-1"
428-
/>
423+
<>
424+
<VSCodeTextField
425+
value={apiConfiguration?.anthropicBaseUrl || ""}
426+
type="url"
427+
onInput={handleInputChange("anthropicBaseUrl")}
428+
placeholder="https://api.anthropic.com"
429+
className="w-full mt-1"
430+
/>
431+
432+
{/* added */}
433+
<Checkbox
434+
checked={apiConfiguration?.anthropicUseAuthToken ?? false}
435+
onChange={handleInputChange("anthropicUseAuthToken", noTransform)}
436+
className="w-full mt-1">
437+
{t("settings:providers.anthropicUseAuthToken")}
438+
</Checkbox>
439+
</>
429440
)}
430441
</div>
431442
</>

webview-ui/src/i18n/locales/ca/settings.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,7 @@
116116
"getRequestyApiKey": "Obtenir clau API de Requesty",
117117
"anthropicApiKey": "Clau API d'Anthropic",
118118
"getAnthropicApiKey": "Obtenir clau API d'Anthropic",
119+
"anthropicUseAuthToken": "Passar la clau API d'Anthropic com a capçalera d'autorització en lloc de X-Api-Key",
119120
"deepSeekApiKey": "Clau API de DeepSeek",
120121
"getDeepSeekApiKey": "Obtenir clau API de DeepSeek",
121122
"geminiApiKey": "Clau API de Gemini",

webview-ui/src/i18n/locales/de/settings.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,7 @@
116116
"openRouterTransformsText": "Prompts und Nachrichtenketten auf Kontextgröße komprimieren (<a>OpenRouter Transformationen</a>)",
117117
"anthropicApiKey": "Anthropic API-Schlüssel",
118118
"getAnthropicApiKey": "Anthropic API-Schlüssel erhalten",
119+
"anthropicUseAuthToken": "Anthropic API-Schlüssel als Authorization-Header anstelle von X-Api-Key übergeben",
119120
"deepSeekApiKey": "DeepSeek API-Schlüssel",
120121
"getDeepSeekApiKey": "DeepSeek API-Schlüssel erhalten",
121122
"geminiApiKey": "Gemini API-Schlüssel",

webview-ui/src/i18n/locales/en/settings.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,7 @@
116116
"openRouterTransformsText": "Compress prompts and message chains to the context size (<a>OpenRouter Transforms</a>)",
117117
"anthropicApiKey": "Anthropic API Key",
118118
"getAnthropicApiKey": "Get Anthropic API Key",
119+
"anthropicUseAuthToken": "Pass Anthropic API Key as Authorization header instead of X-Api-Key",
119120
"deepSeekApiKey": "DeepSeek API Key",
120121
"getDeepSeekApiKey": "Get DeepSeek API Key",
121122
"geminiApiKey": "Gemini API Key",

0 commit comments

Comments
 (0)