feat: add UI checkbox for Bedrock backend option in LiteLLM provider

- Add litellmUseAzureBedrock option to provider settings schema
- Add checkbox UI in LiteLLM settings to let users specify Bedrock backend
- Update isBedrockModel() to use user-specified option over auto-detection
- Add comprehensive tests for the new option
- Add English translations for the new setting
This commit is contained in:
Roo Code 2025-12-21 23:51:07 +00:00
parent bbd325f539
commit 5d474ee0ca
5 changed files with 138 additions and 2 deletions

View file

@ -374,6 +374,7 @@ const litellmSchema = baseProviderSettingsSchema.extend({
litellmApiKey: z.string().optional(),
litellmModelId: z.string().optional(),
litellmUsePromptCache: z.boolean().optional(),
litellmUseAzureBedrock: z.boolean().optional(),
})
const cerebrasSchema = apiModelIdProviderModelSchema.extend({

View file

@ -401,7 +401,117 @@ describe("LiteLLMHandler", () => {
})
describe("Bedrock model handling", () => {
it("should exclude parallel_tool_calls for Bedrock models when using native tools", async () => {
it("should exclude parallel_tool_calls when litellmUseAzureBedrock is explicitly true", async () => {
const options: ApiHandlerOptions = {
...mockOptions,
litellmModelId: "gpt-4", // Non-Bedrock model ID
litellmUseAzureBedrock: true, // Explicitly set to Bedrock
}
handler = new LiteLLMHandler(options)
const systemPrompt = "You are a helpful assistant"
const messages: Anthropic.Messages.MessageParam[] = [{ role: "user", content: "Test" }]
// Mock the stream response
const mockStream = {
async *[Symbol.asyncIterator]() {
yield {
choices: [{ delta: { content: "Response" } }],
usage: {
prompt_tokens: 10,
completion_tokens: 5,
},
}
},
}
mockCreate.mockReturnValue({
withResponse: vi.fn().mockResolvedValue({ data: mockStream }),
})
const metadata = {
taskId: "test-task",
tools: [
{
type: "function" as const,
function: {
name: "test_tool",
description: "A test tool",
parameters: { type: "object", properties: {} },
},
},
],
toolProtocol: "native" as const,
parallelToolCalls: true,
}
const generator = handler.createMessage(systemPrompt, messages, metadata)
for await (const chunk of generator) {
// Consume the generator
}
// Verify that parallel_tool_calls is NOT included when litellmUseAzureBedrock is true
const createCall = mockCreate.mock.calls[0][0]
expect(createCall.parallel_tool_calls).toBeUndefined()
expect(createCall.tools).toBeDefined()
})
it("should include parallel_tool_calls when litellmUseAzureBedrock is explicitly false", async () => {
const options: ApiHandlerOptions = {
...mockOptions,
litellmModelId: "bedrock/anthropic.claude-3-5-sonnet-20241022-v2:0", // Bedrock model ID
litellmUseAzureBedrock: false, // Explicitly set to NOT Bedrock
}
handler = new LiteLLMHandler(options)
const systemPrompt = "You are a helpful assistant"
const messages: Anthropic.Messages.MessageParam[] = [{ role: "user", content: "Test" }]
// Mock the stream response
const mockStream = {
async *[Symbol.asyncIterator]() {
yield {
choices: [{ delta: { content: "Response" } }],
usage: {
prompt_tokens: 10,
completion_tokens: 5,
},
}
},
}
mockCreate.mockReturnValue({
withResponse: vi.fn().mockResolvedValue({ data: mockStream }),
})
const metadata = {
taskId: "test-task",
tools: [
{
type: "function" as const,
function: {
name: "test_tool",
description: "A test tool",
parameters: { type: "object", properties: {} },
},
},
],
toolProtocol: "native" as const,
parallelToolCalls: true,
}
const generator = handler.createMessage(systemPrompt, messages, metadata)
for await (const chunk of generator) {
// Consume the generator
}
// Verify that parallel_tool_calls IS included when litellmUseAzureBedrock is false
const createCall = mockCreate.mock.calls[0][0]
expect(createCall.parallel_tool_calls).toBe(true)
expect(createCall.tools).toBeDefined()
})
it("should auto-detect and exclude parallel_tool_calls for Bedrock models when litellmUseAzureBedrock is not set", async () => {
const bedrockModels = ["bedrock/anthropic.claude-3-5-sonnet-20241022-v2:0", "amazon.titan-text-express-v1"]
for (const modelId of bedrockModels) {
@ -461,7 +571,7 @@ describe("LiteLLMHandler", () => {
}
})
it("should include parallel_tool_calls for non-Bedrock models when using native tools", async () => {
it("should auto-detect and include parallel_tool_calls for non-Bedrock models when litellmUseAzureBedrock is not set", async () => {
const nonBedrockModels = [
"gpt-4",
"claude-3-opus",

View file

@ -41,9 +41,18 @@ export class LiteLLMHandler extends RouterProvider implements SingleCompletionHa
/**
* Check if the model is routed through AWS Bedrock
* Bedrock doesn't support the parallel_tool_calls parameter
*
* If the user has explicitly set litellmUseAzureBedrock, use that setting.
* Otherwise, fall back to auto-detection based on model ID patterns.
* Note: We exclude 'anthropic.' prefix as it can match direct Anthropic API access through LiteLLM
*/
private isBedrockModel(modelId: string): boolean {
// User-specified option takes precedence
if (this.options.litellmUseAzureBedrock !== undefined) {
return this.options.litellmUseAzureBedrock
}
// Fall back to auto-detection
const lowerModel = modelId.toLowerCase()
return (
lowerModel.includes("bedrock") ||

View file

@ -156,6 +156,20 @@ export const LiteLLM = ({
simplifySettings={simplifySettings}
/>
{/* Bedrock backend option */}
<div className="mt-4">
<VSCodeCheckbox
checked={apiConfiguration.litellmUseAzureBedrock || false}
onChange={(e: any) => {
setApiConfigurationField("litellmUseAzureBedrock", e.target.checked)
}}>
<span className="font-medium">{t("settings:providers.litellmUseAzureBedrock")}</span>
</VSCodeCheckbox>
<div className="text-sm text-vscode-descriptionForeground ml-6 mt-1">
{t("settings:providers.litellmUseAzureBedrockDescription")}
</div>
</div>
{/* Show prompt caching option if the selected model supports it */}
{(() => {
const selectedModelId = apiConfiguration.litellmModelId || litellmDefaultModelId

View file

@ -370,6 +370,8 @@
"getXaiApiKey": "Get xAI API Key",
"litellmApiKey": "LiteLLM API Key",
"litellmBaseUrl": "LiteLLM Base URL",
"litellmUseAzureBedrock": "Backend is AWS Bedrock",
"litellmUseAzureBedrockDescription": "Enable this if your LiteLLM proxy routes to AWS Bedrock models. This ensures Bedrock-incompatible parameters are excluded from requests.",
"awsCredentials": "AWS Credentials",
"awsProfile": "AWS Profile",
"awsApiKey": "Amazon Bedrock API Key",