Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
63 changes: 63 additions & 0 deletions src/api/providers/__tests__/bedrock.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1287,4 +1287,67 @@ describe("AwsBedrockHandler", () => {
expect(mockCaptureException).toHaveBeenCalled()
})
})

describe("prompt cache default behavior", () => {
function setupMockStreamText() {
async function* mockFullStream() {
yield { type: "text-delta", text: "response" }
}
mockStreamText.mockReturnValue({
fullStream: mockFullStream(),
usage: Promise.resolve({ inputTokens: 10, outputTokens: 5 }),
providerMetadata: Promise.resolve({}),
})
}

const messages: Anthropic.Messages.MessageParam[] = [{ role: "user", content: "Hello" }]

it("should enable prompt caching by default when awsUsePromptCache is undefined", async () => {
setupMockStreamText()

const defaultHandler = new AwsBedrockHandler({
apiModelId: "anthropic.claude-3-5-sonnet-20241022-v2:0",
awsAccessKey: "test-access-key",
awsSecretKey: "test-secret-key",
awsRegion: "us-east-1",
// awsUsePromptCache is intentionally omitted (undefined)
})

const generator = defaultHandler.createMessage("You are a helpful assistant", messages)
for await (const _chunk of generator) {
// consume the stream
}

expect(mockStreamText).toHaveBeenCalledTimes(1)
const callArgs = mockStreamText.mock.calls[0][0]

// systemProviderOptions should include cachePoint since prompt caching defaults to ON
expect(callArgs.systemProviderOptions).toEqual({
bedrock: { cachePoint: { type: "default" } },
})
})

it("should disable prompt caching when awsUsePromptCache is explicitly false", async () => {
setupMockStreamText()

const disabledHandler = new AwsBedrockHandler({
apiModelId: "anthropic.claude-3-5-sonnet-20241022-v2:0",
awsAccessKey: "test-access-key",
awsSecretKey: "test-secret-key",
awsRegion: "us-east-1",
awsUsePromptCache: false,
})

const generator = disabledHandler.createMessage("You are a helpful assistant", messages)
for await (const _chunk of generator) {
// consume the stream
}

expect(mockStreamText).toHaveBeenCalledTimes(1)
const callArgs = mockStreamText.mock.calls[0][0]

// systemProviderOptions should NOT include cachePoint since caching is explicitly disabled
expect(callArgs.systemProviderOptions).toBeUndefined()
})
})
})
4 changes: 3 additions & 1 deletion src/api/providers/bedrock.ts
Original file line number Diff line number Diff line change
Expand Up @@ -271,7 +271,9 @@ export class AwsBedrockHandler extends BaseProvider implements SingleCompletionH
// We identify targets in the ORIGINAL Anthropic messages (before AI SDK conversion)
// because convertToAiSdkMessages() splits user messages containing tool_results into
// separate "tool" + "user" role messages, which would skew naive counting.
const usePromptCache = Boolean(this.options.awsUsePromptCache && this.supportsAwsPromptCache(modelConfig))
const usePromptCache = Boolean(
(this.options.awsUsePromptCache ?? true) && this.supportsAwsPromptCache(modelConfig),
)

if (usePromptCache) {
const cachePointOption = { bedrock: { cachePoint: { type: "default" as const } } }
Expand Down
2 changes: 1 addition & 1 deletion webview-ui/src/components/settings/providers/Bedrock.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,7 @@ export const Bedrock = ({ apiConfiguration, setApiConfigurationField, selectedMo
{selectedModelInfo?.supportsPromptCache && (
<>
<Checkbox
checked={apiConfiguration?.awsUsePromptCache || false}
checked={apiConfiguration?.awsUsePromptCache ?? true}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

UI/backend mismatch: this line renders the checkbox as checked when awsUsePromptCache is undefined (the case for any user who never explicitly toggled this setting). However, the backend at src/api/providers/bedrock.ts:274 evaluates Boolean(this.options.awsUsePromptCache && ...), which treats undefined as falsy -- so caching is actually OFF. The result is a checkbox that shows "enabled" while the backend is not caching. To make this consistent, the backend line should also default to true, e.g. Boolean((this.options.awsUsePromptCache ?? true) && this.supportsAwsPromptCache(modelConfig)).

Fix it with Roo Code or mention @roomote and request a fix.

onChange={handleInputChange("awsUsePromptCache", noTransform)}>
<div className="flex items-center gap-1">
<span>{t("settings:providers.enablePromptCaching")}</span>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -464,6 +464,52 @@ describe("useSelectedModel", () => {
})
})

describe("bedrock provider with custom ARN", () => {
beforeEach(() => {
mockUseRouterModels.mockReturnValue({
data: {
openrouter: {},
requesty: {},
litellm: {},
},
isLoading: false,
isError: false,
} as any)

mockUseOpenRouterModelProviders.mockReturnValue({
data: {},
isLoading: false,
isError: false,
} as any)
})

it("should enable supportsPromptCache for custom-arn model", () => {
const apiConfiguration: ProviderSettings = {
apiProvider: "bedrock",
apiModelId: "custom-arn",
}

const wrapper = createWrapper()
const { result } = renderHook(() => useSelectedModel(apiConfiguration), { wrapper })

expect(result.current.id).toBe("custom-arn")
expect(result.current.info?.supportsPromptCache).toBe(true)
})

it("should enable supportsImages for custom-arn model", () => {
const apiConfiguration: ProviderSettings = {
apiProvider: "bedrock",
apiModelId: "custom-arn",
}

const wrapper = createWrapper()
const { result } = renderHook(() => useSelectedModel(apiConfiguration), { wrapper })

expect(result.current.id).toBe("custom-arn")
expect(result.current.info?.supportsImages).toBe(true)
})
})

describe("litellm provider", () => {
beforeEach(() => {
mockUseOpenRouterModelProviders.mockReturnValue({
Expand Down
2 changes: 1 addition & 1 deletion webview-ui/src/components/ui/hooks/useSelectedModel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,7 @@ function getSelectedModel({
if (id === "custom-arn") {
return {
id,
info: { maxTokens: 5000, contextWindow: 128_000, supportsPromptCache: false, supportsImages: true },
info: { maxTokens: 5000, contextWindow: 128_000, supportsPromptCache: true, supportsImages: true },
}
}

Expand Down
Loading