From cc01dd11144a0084d52ca39cbefed6dff4bffc06 Mon Sep 17 00:00:00 2001 From: Kevin White Date: Sun, 11 May 2025 03:11:40 -0600 Subject: [PATCH 01/22] feat: Add custom VPC endpoint support for AWS Bedrock --- src/api/providers/bedrock.ts | 2 ++ src/exports/roo-code.d.ts | 1 + src/exports/types.ts | 1 + src/schemas/index.ts | 2 ++ .../components/settings/providers/Bedrock.tsx | 19 +++++++++++++++++++ 5 files changed, 25 insertions(+) diff --git a/src/api/providers/bedrock.ts b/src/api/providers/bedrock.ts index b388748440..28350d2676 100644 --- a/src/api/providers/bedrock.ts +++ b/src/api/providers/bedrock.ts @@ -165,6 +165,8 @@ export class AwsBedrockHandler extends BaseProvider implements SingleCompletionH const clientConfig: BedrockRuntimeClientConfig = { region: this.options.awsRegion, + // Add the endpoint configuration when specified + ...(this.options.awsBedrockEndpoint && { endpoint: this.options.awsBedrockEndpoint }), } if (this.options.awsUseProfile && this.options.awsProfile) { diff --git a/src/exports/roo-code.d.ts b/src/exports/roo-code.d.ts index d0d82fa39e..b33c9d6b09 100644 --- a/src/exports/roo-code.d.ts +++ b/src/exports/roo-code.d.ts @@ -46,6 +46,7 @@ type ProviderSettings = { awsProfile?: string | undefined awsUseProfile?: boolean | undefined awsCustomArn?: string | undefined + awsBedrockEndpoint?: string | undefined vertexKeyFile?: string | undefined vertexJsonCredentials?: string | undefined vertexProjectId?: string | undefined diff --git a/src/exports/types.ts b/src/exports/types.ts index 05d492b8cc..57862042cb 100644 --- a/src/exports/types.ts +++ b/src/exports/types.ts @@ -47,6 +47,7 @@ type ProviderSettings = { awsProfile?: string | undefined awsUseProfile?: boolean | undefined awsCustomArn?: string | undefined + awsBedrockEndpoint?: string | undefined vertexKeyFile?: string | undefined vertexJsonCredentials?: string | undefined vertexProjectId?: string | undefined diff --git a/src/schemas/index.ts b/src/schemas/index.ts index 094b11b10d..a819a2f495 100644 --- a/src/schemas/index.ts +++ b/src/schemas/index.ts @@ -371,6 +371,7 @@ export const providerSettingsSchema = z.object({ awsProfile: z.string().optional(), awsUseProfile: z.boolean().optional(), awsCustomArn: z.string().optional(), + awsBedrockEndpoint: z.string().optional(), // Google Vertex vertexKeyFile: z.string().optional(), vertexJsonCredentials: z.string().optional(), @@ -479,6 +480,7 @@ const providerSettingsRecord: ProviderSettingsRecord = { awsProfile: undefined, awsUseProfile: undefined, awsCustomArn: undefined, + awsBedrockEndpoint: undefined, // Google Vertex vertexKeyFile: undefined, vertexJsonCredentials: undefined, diff --git a/webview-ui/src/components/settings/providers/Bedrock.tsx b/webview-ui/src/components/settings/providers/Bedrock.tsx index fc69e74dde..30f6d751c6 100644 --- a/webview-ui/src/components/settings/providers/Bedrock.tsx +++ b/webview-ui/src/components/settings/providers/Bedrock.tsx @@ -121,6 +121,25 @@ export const Bedrock = ({ apiConfiguration, setApiConfigurationField, selectedMo {t("settings:providers.cacheUsageNote")} + { + const isChecked = e.target.checked; + if (!isChecked) { + setApiConfigurationField("awsBedrockEndpoint", ""); + } + }}> + {t("settings:providers.useCustomVpcEndpoint") || "Use custom VPC endpoint"} + + {apiConfiguration?.awsBedrockEndpoint !== undefined && apiConfiguration?.awsBedrockEndpoint !== "" ? ( + + + + ) : null} ) } From 91b555756353af33475edbd29d43c7bf0a499152 Mon Sep 17 00:00:00 2001 From: Kevin White Date: Sun, 11 May 2025 03:14:54 -0600 Subject: [PATCH 02/22] fix: Fix TypeScript error in Bedrock.tsx --- webview-ui/src/components/settings/providers/Bedrock.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/webview-ui/src/components/settings/providers/Bedrock.tsx b/webview-ui/src/components/settings/providers/Bedrock.tsx index 30f6d751c6..8b762bc539 100644 --- a/webview-ui/src/components/settings/providers/Bedrock.tsx +++ b/webview-ui/src/components/settings/providers/Bedrock.tsx @@ -124,7 +124,7 @@ export const Bedrock = ({ apiConfiguration, setApiConfigurationField, selectedMo { - const isChecked = e.target.checked; + const isChecked = (e as any).target.checked; if (!isChecked) { setApiConfigurationField("awsBedrockEndpoint", ""); } From 3d3433ba1d550f9368024558618d722475b57d18 Mon Sep 17 00:00:00 2001 From: Kevin White Date: Sun, 11 May 2025 03:36:43 -0600 Subject: [PATCH 03/22] fix: Update VPC endpoint UI to match Cline's implementation --- .../src/components/settings/providers/Bedrock.tsx | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/webview-ui/src/components/settings/providers/Bedrock.tsx b/webview-ui/src/components/settings/providers/Bedrock.tsx index 8b762bc539..bc9ff08d0f 100644 --- a/webview-ui/src/components/settings/providers/Bedrock.tsx +++ b/webview-ui/src/components/settings/providers/Bedrock.tsx @@ -131,15 +131,16 @@ export const Bedrock = ({ apiConfiguration, setApiConfigurationField, selectedMo }}> {t("settings:providers.useCustomVpcEndpoint") || "Use custom VPC endpoint"} - {apiConfiguration?.awsBedrockEndpoint !== undefined && apiConfiguration?.awsBedrockEndpoint !== "" ? ( + {!!apiConfiguration?.awsBedrockEndpoint && ( - - - ) : null} + placeholder="Enter VPC Endpoint URL (optional)" + className="ml-6" + /> + )} ) } From 019f2c66491b80d4c08ce7d54722c638e6ee6a43 Mon Sep 17 00:00:00 2001 From: Kevin White Date: Sun, 11 May 2025 04:00:03 -0600 Subject: [PATCH 04/22] Fix AWS Bedrock VPC endpoint UI implementation - Changed checkbox label to 'Use custom VPC endpoint' to match Cline - Fixed conditional rendering to show text field when checkbox is checked - Ensured placeholder text appears correctly - Maintained proper styling for consistency --- .../src/components/settings/providers/Bedrock.tsx | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/webview-ui/src/components/settings/providers/Bedrock.tsx b/webview-ui/src/components/settings/providers/Bedrock.tsx index bc9ff08d0f..39755474f9 100644 --- a/webview-ui/src/components/settings/providers/Bedrock.tsx +++ b/webview-ui/src/components/settings/providers/Bedrock.tsx @@ -122,18 +122,18 @@ export const Bedrock = ({ apiConfiguration, setApiConfigurationField, selectedMo { - const isChecked = (e as any).target.checked; + const isChecked = (e as any).target.checked if (!isChecked) { - setApiConfigurationField("awsBedrockEndpoint", ""); + setApiConfigurationField("awsBedrockEndpoint", "") } }}> - {t("settings:providers.useCustomVpcEndpoint") || "Use custom VPC endpoint"} + Use custom VPC endpoint - {!!apiConfiguration?.awsBedrockEndpoint && ( + {apiConfiguration?.awsBedrockEndpoint !== undefined && apiConfiguration?.awsBedrockEndpoint !== null && ( Date: Sun, 11 May 2025 04:10:13 -0600 Subject: [PATCH 05/22] Fix AWS Bedrock VPC endpoint UI implementation to match Cline exactly - Added state variable to track checkbox selection - Fixed conditional rendering to show/hide text field based on checkbox state - Maintained proper styling and placeholder text --- .../src/components/settings/providers/Bedrock.tsx | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/webview-ui/src/components/settings/providers/Bedrock.tsx b/webview-ui/src/components/settings/providers/Bedrock.tsx index 39755474f9..26ebca6d47 100644 --- a/webview-ui/src/components/settings/providers/Bedrock.tsx +++ b/webview-ui/src/components/settings/providers/Bedrock.tsx @@ -1,4 +1,4 @@ -import { useCallback } from "react" +import { useCallback, useState } from "react" import { Checkbox } from "vscrui" import { VSCodeTextField, VSCodeRadio, VSCodeRadioGroup } from "@vscode/webview-ui-toolkit/react" @@ -18,6 +18,7 @@ type BedrockProps = { export const Bedrock = ({ apiConfiguration, setApiConfigurationField, selectedModelInfo }: BedrockProps) => { const { t } = useAppTranslation() + const [awsEndpointSelected, setAwsEndpointSelected] = useState(!!apiConfiguration?.awsBedrockEndpoint) const handleInputChange = useCallback( ( @@ -122,18 +123,19 @@ export const Bedrock = ({ apiConfiguration, setApiConfigurationField, selectedMo { const isChecked = (e as any).target.checked + setAwsEndpointSelected(isChecked) if (!isChecked) { setApiConfigurationField("awsBedrockEndpoint", "") } }}> Use custom VPC endpoint - {apiConfiguration?.awsBedrockEndpoint !== undefined && apiConfiguration?.awsBedrockEndpoint !== null && ( + {awsEndpointSelected && ( Date: Sun, 11 May 2025 23:49:46 -0600 Subject: [PATCH 06/22] Fix AWS Bedrock VPC endpoint UI implementation with proper event handling - Fixed checkbox onChange handler to accept boolean directly instead of event object - Added unit tests to verify the behavior - Maintained proper styling and placeholder text --- .../components/settings/providers/Bedrock.tsx | 3 +- .../providers/__tests__/Bedrock.test.tsx | 115 ++++++++++++++++++ 2 files changed, 116 insertions(+), 2 deletions(-) create mode 100644 webview-ui/src/components/settings/providers/__tests__/Bedrock.test.tsx diff --git a/webview-ui/src/components/settings/providers/Bedrock.tsx b/webview-ui/src/components/settings/providers/Bedrock.tsx index 26ebca6d47..2f1832ad67 100644 --- a/webview-ui/src/components/settings/providers/Bedrock.tsx +++ b/webview-ui/src/components/settings/providers/Bedrock.tsx @@ -124,8 +124,7 @@ export const Bedrock = ({ apiConfiguration, setApiConfigurationField, selectedMo { - const isChecked = (e as any).target.checked + onChange={(isChecked) => { setAwsEndpointSelected(isChecked) if (!isChecked) { setApiConfigurationField("awsBedrockEndpoint", "") diff --git a/webview-ui/src/components/settings/providers/__tests__/Bedrock.test.tsx b/webview-ui/src/components/settings/providers/__tests__/Bedrock.test.tsx new file mode 100644 index 0000000000..78437cf87b --- /dev/null +++ b/webview-ui/src/components/settings/providers/__tests__/Bedrock.test.tsx @@ -0,0 +1,115 @@ +import React from "react" +import { render, screen, fireEvent } from "@testing-library/react" +import { Bedrock } from "../Bedrock" +import { ApiConfiguration } from "@roo/shared/api" + +// Mock the vscrui Checkbox component +jest.mock("vscrui", () => ({ + Checkbox: ({ children, checked, onChange }: any) => ( + + ), +})) + +// Mock the VSCodeTextField component +jest.mock("@vscode/webview-ui-toolkit/react", () => ({ + VSCodeTextField: ({ children, value, onInput, placeholder, className, style }: any) => ( +
+ {children} + onInput && onInput(e)} + placeholder={placeholder} + data-testid="vpc-endpoint-input" + /> +
+ ), + VSCodeRadio: () =>
Radio
, + VSCodeRadioGroup: ({ children }: any) =>
{children}
, +})) + +// Mock the translation hook +jest.mock("@src/i18n/TranslationContext", () => ({ + useAppTranslation: () => ({ + t: (key: string) => key, + }), +})) + +// Mock the UI components +jest.mock("@src/components/ui", () => ({ + Select: ({ children }: any) =>
{children}
, + SelectContent: ({ children }: any) =>
{children}
, + SelectItem: () =>
Item
, + SelectTrigger: ({ children }: any) =>
{children}
, + SelectValue: () =>
Value
, +})) + +// Mock the constants +jest.mock("../../constants", () => ({ + AWS_REGIONS: [{ value: "us-east-1", label: "US East (N. Virginia)" }], +})) + +describe("Bedrock Component", () => { + const mockSetApiConfigurationField = jest.fn() + + beforeEach(() => { + jest.clearAllMocks() + }) + + it("should show text field when VPC endpoint checkbox is checked", () => { + // Initial render with checkbox unchecked + const apiConfiguration: Partial = { + awsBedrockEndpoint: "", + } + + render( + , + ) + + // Text field should not be visible initially + expect(screen.queryByTestId("vpc-endpoint-input")).not.toBeInTheDocument() + + // Click the checkbox + fireEvent.click(screen.getByTestId("checkbox-input-use-custom-vpc-endpoint")) + + // Text field should now be visible + expect(screen.getByTestId("vpc-endpoint-input")).toBeInTheDocument() + }) + + it("should hide text field when VPC endpoint checkbox is unchecked", () => { + // Initial render with checkbox checked + const apiConfiguration: Partial = { + awsBedrockEndpoint: "https://example.com", + } + + render( + , + ) + + // Text field should be visible initially + expect(screen.getByTestId("vpc-endpoint-input")).toBeInTheDocument() + + // Click the checkbox to uncheck it + fireEvent.click(screen.getByTestId("checkbox-input-use-custom-vpc-endpoint")) + + // Text field should now be hidden + expect(screen.queryByTestId("vpc-endpoint-input")).not.toBeInTheDocument() + + // Should call setApiConfigurationField to clear the endpoint + expect(mockSetApiConfigurationField).toHaveBeenCalledWith("awsBedrockEndpoint", "") + }) +}) From cae91f200f0199779d82c4dc079a1bdf62b5098b Mon Sep 17 00:00:00 2001 From: Kevin White Date: Sun, 11 May 2025 23:59:51 -0600 Subject: [PATCH 07/22] Update Bedrock VPC endpoint tests with proper test IDs --- .../providers/__tests__/Bedrock.test.tsx | 39 +++++++++++++------ 1 file changed, 27 insertions(+), 12 deletions(-) diff --git a/webview-ui/src/components/settings/providers/__tests__/Bedrock.test.tsx b/webview-ui/src/components/settings/providers/__tests__/Bedrock.test.tsx index 78437cf87b..c187137f68 100644 --- a/webview-ui/src/components/settings/providers/__tests__/Bedrock.test.tsx +++ b/webview-ui/src/components/settings/providers/__tests__/Bedrock.test.tsx @@ -20,18 +20,31 @@ jest.mock("vscrui", () => ({ // Mock the VSCodeTextField component jest.mock("@vscode/webview-ui-toolkit/react", () => ({ - VSCodeTextField: ({ children, value, onInput, placeholder, className, style }: any) => ( -
- {children} - onInput && onInput(e)} - placeholder={placeholder} - data-testid="vpc-endpoint-input" - /> -
- ), + VSCodeTextField: ({ children, value, onInput, placeholder, className, style }: any) => { + // Special case for VPC endpoint field + if (placeholder === "Enter VPC Endpoint URL (optional)") { + return ( +
+ {children} + onInput && onInput(e)} + placeholder={placeholder} + data-testid="vpc-endpoint-input" + /> +
+ ) + } + + // Regular text fields + return ( +
+ {children} + onInput && onInput(e)} placeholder={placeholder} /> +
+ ) + }, VSCodeRadio: () =>
Radio
, VSCodeRadioGroup: ({ children }: any) =>
{children}
, })) @@ -68,6 +81,7 @@ describe("Bedrock Component", () => { // Initial render with checkbox unchecked const apiConfiguration: Partial = { awsBedrockEndpoint: "", + awsUseProfile: true, // Use profile to avoid rendering other text fields } render( @@ -91,6 +105,7 @@ describe("Bedrock Component", () => { // Initial render with checkbox checked const apiConfiguration: Partial = { awsBedrockEndpoint: "https://example.com", + awsUseProfile: true, // Use profile to avoid rendering other text fields } render( From 8e9c4fad6895a637547f33bd497339288c837edb Mon Sep 17 00:00:00 2001 From: Kevin White Date: Mon, 12 May 2025 00:07:02 -0600 Subject: [PATCH 08/22] Improve AWS Bedrock VPC endpoint text field alignment - Removed left margin from text field to align with checkbox - Maintained proper styling and placeholder text --- webview-ui/src/components/settings/providers/Bedrock.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/webview-ui/src/components/settings/providers/Bedrock.tsx b/webview-ui/src/components/settings/providers/Bedrock.tsx index 2f1832ad67..3e94f4694d 100644 --- a/webview-ui/src/components/settings/providers/Bedrock.tsx +++ b/webview-ui/src/components/settings/providers/Bedrock.tsx @@ -139,7 +139,6 @@ export const Bedrock = ({ apiConfiguration, setApiConfigurationField, selectedMo type="url" onInput={handleInputChange("awsBedrockEndpoint")} placeholder="Enter VPC Endpoint URL (optional)" - className="ml-6" /> )} From 24fe42bdcad6aa811ee439c178ad8f22926967b0 Mon Sep 17 00:00:00 2001 From: Kevin White Date: Mon, 12 May 2025 00:31:20 -0600 Subject: [PATCH 09/22] Preserve AWS Bedrock VPC endpoint URL when toggling checkbox - Added awsBedrockEndpointEnabled field to schema - Modified Bedrock provider to check both endpoint URL and enabled flag - Updated UI to preserve endpoint URL when checkbox is toggled - Maintained proper alignment with checkbox --- src/api/providers/bedrock.ts | 5 +++-- src/exports/roo-code.d.ts | 1 + src/exports/types.ts | 1 + src/schemas/index.ts | 2 ++ .../src/components/settings/providers/Bedrock.tsx | 13 ++++++++----- 5 files changed, 15 insertions(+), 7 deletions(-) diff --git a/src/api/providers/bedrock.ts b/src/api/providers/bedrock.ts index 28350d2676..85cef17f8e 100644 --- a/src/api/providers/bedrock.ts +++ b/src/api/providers/bedrock.ts @@ -165,8 +165,9 @@ export class AwsBedrockHandler extends BaseProvider implements SingleCompletionH const clientConfig: BedrockRuntimeClientConfig = { region: this.options.awsRegion, - // Add the endpoint configuration when specified - ...(this.options.awsBedrockEndpoint && { endpoint: this.options.awsBedrockEndpoint }), + // Add the endpoint configuration when specified and enabled + ...(this.options.awsBedrockEndpoint && + this.options.awsBedrockEndpointEnabled && { endpoint: this.options.awsBedrockEndpoint }), } if (this.options.awsUseProfile && this.options.awsProfile) { diff --git a/src/exports/roo-code.d.ts b/src/exports/roo-code.d.ts index b33c9d6b09..5f46307469 100644 --- a/src/exports/roo-code.d.ts +++ b/src/exports/roo-code.d.ts @@ -47,6 +47,7 @@ type ProviderSettings = { awsUseProfile?: boolean | undefined awsCustomArn?: string | undefined awsBedrockEndpoint?: string | undefined + awsBedrockEndpointEnabled?: boolean | undefined vertexKeyFile?: string | undefined vertexJsonCredentials?: string | undefined vertexProjectId?: string | undefined diff --git a/src/exports/types.ts b/src/exports/types.ts index 57862042cb..920f064c8a 100644 --- a/src/exports/types.ts +++ b/src/exports/types.ts @@ -48,6 +48,7 @@ type ProviderSettings = { awsUseProfile?: boolean | undefined awsCustomArn?: string | undefined awsBedrockEndpoint?: string | undefined + awsBedrockEndpointEnabled?: boolean | undefined vertexKeyFile?: string | undefined vertexJsonCredentials?: string | undefined vertexProjectId?: string | undefined diff --git a/src/schemas/index.ts b/src/schemas/index.ts index a819a2f495..212fdb33a8 100644 --- a/src/schemas/index.ts +++ b/src/schemas/index.ts @@ -372,6 +372,7 @@ export const providerSettingsSchema = z.object({ awsUseProfile: z.boolean().optional(), awsCustomArn: z.string().optional(), awsBedrockEndpoint: z.string().optional(), + awsBedrockEndpointEnabled: z.boolean().optional(), // Google Vertex vertexKeyFile: z.string().optional(), vertexJsonCredentials: z.string().optional(), @@ -481,6 +482,7 @@ const providerSettingsRecord: ProviderSettingsRecord = { awsUseProfile: undefined, awsCustomArn: undefined, awsBedrockEndpoint: undefined, + awsBedrockEndpointEnabled: undefined, // Google Vertex vertexKeyFile: undefined, vertexJsonCredentials: undefined, diff --git a/webview-ui/src/components/settings/providers/Bedrock.tsx b/webview-ui/src/components/settings/providers/Bedrock.tsx index 3e94f4694d..f5712f16d2 100644 --- a/webview-ui/src/components/settings/providers/Bedrock.tsx +++ b/webview-ui/src/components/settings/providers/Bedrock.tsx @@ -1,4 +1,4 @@ -import { useCallback, useState } from "react" +import { useCallback, useState, useEffect } from "react" import { Checkbox } from "vscrui" import { VSCodeTextField, VSCodeRadio, VSCodeRadioGroup } from "@vscode/webview-ui-toolkit/react" @@ -18,7 +18,12 @@ type BedrockProps = { export const Bedrock = ({ apiConfiguration, setApiConfigurationField, selectedModelInfo }: BedrockProps) => { const { t } = useAppTranslation() - const [awsEndpointSelected, setAwsEndpointSelected] = useState(!!apiConfiguration?.awsBedrockEndpoint) + const [awsEndpointSelected, setAwsEndpointSelected] = useState(!!apiConfiguration?.awsBedrockEndpointEnabled) + + // Update the endpoint enabled state when the configuration changes + useEffect(() => { + setAwsEndpointSelected(!!apiConfiguration?.awsBedrockEndpointEnabled) + }, [apiConfiguration?.awsBedrockEndpointEnabled]) const handleInputChange = useCallback( ( @@ -126,9 +131,7 @@ export const Bedrock = ({ apiConfiguration, setApiConfigurationField, selectedMo checked={awsEndpointSelected} onChange={(isChecked) => { setAwsEndpointSelected(isChecked) - if (!isChecked) { - setApiConfigurationField("awsBedrockEndpoint", "") - } + setApiConfigurationField("awsBedrockEndpointEnabled", isChecked) }}> Use custom VPC endpoint
From 1b16465fecd1e74ecd9d33c74fc9d2ed4194415b Mon Sep 17 00:00:00 2001 From: Kevin White Date: Mon, 12 May 2025 01:23:09 -0600 Subject: [PATCH 10/22] Implement AWS Bedrock Custom VPC Endpoint functionality --- .../__tests__/bedrock-vpc-endpoint.test.ts | 178 +++++++++++++ .../providers/__tests__/Bedrock.test.tsx | 237 +++++++++++++++++- 2 files changed, 413 insertions(+), 2 deletions(-) create mode 100644 src/api/providers/__tests__/bedrock-vpc-endpoint.test.ts diff --git a/src/api/providers/__tests__/bedrock-vpc-endpoint.test.ts b/src/api/providers/__tests__/bedrock-vpc-endpoint.test.ts new file mode 100644 index 0000000000..e347620ce7 --- /dev/null +++ b/src/api/providers/__tests__/bedrock-vpc-endpoint.test.ts @@ -0,0 +1,178 @@ +// Mock AWS SDK credential providers +jest.mock("@aws-sdk/credential-providers", () => { + const mockFromIni = jest.fn().mockReturnValue({ + accessKeyId: "profile-access-key", + secretAccessKey: "profile-secret-key", + }) + return { fromIni: mockFromIni } +}) + +// Mock BedrockRuntimeClient and ConverseStreamCommand +const mockBedrockRuntimeClient = jest.fn() +const mockSend = jest.fn().mockResolvedValue({ + stream: [], +}) + +jest.mock("@aws-sdk/client-bedrock-runtime", () => ({ + BedrockRuntimeClient: mockBedrockRuntimeClient.mockImplementation(() => ({ + send: mockSend, + })), + ConverseStreamCommand: jest.fn(), + ConverseCommand: jest.fn(), +})) + +import { AwsBedrockHandler } from "../bedrock" + +describe("AWS Bedrock VPC Endpoint Functionality", () => { + beforeEach(() => { + // Clear all mocks before each test + jest.clearAllMocks() + }) + + // Test Scenario 1: Input Validation Test + describe("VPC Endpoint URL Validation", () => { + it("should configure client with endpoint URL when both URL and enabled flag are provided", () => { + // Create handler with endpoint URL and enabled flag + new AwsBedrockHandler({ + apiModelId: "anthropic.claude-3-5-sonnet-20241022-v2:0", + awsAccessKey: "test-access-key", + awsSecretKey: "test-secret-key", + awsRegion: "us-east-1", + awsBedrockEndpoint: "https://bedrock-vpc.example.com", + awsBedrockEndpointEnabled: true, + }) + + // Verify the client was created with the correct endpoint + expect(mockBedrockRuntimeClient).toHaveBeenCalledWith( + expect.objectContaining({ + region: "us-east-1", + endpoint: "https://bedrock-vpc.example.com", + }), + ) + }) + + it("should not configure client with endpoint URL when URL is provided but enabled flag is false", () => { + // Create handler with endpoint URL but disabled flag + new AwsBedrockHandler({ + apiModelId: "anthropic.claude-3-5-sonnet-20241022-v2:0", + awsAccessKey: "test-access-key", + awsSecretKey: "test-secret-key", + awsRegion: "us-east-1", + awsBedrockEndpoint: "https://bedrock-vpc.example.com", + awsBedrockEndpointEnabled: false, + }) + + // Verify the client was created without the endpoint + expect(mockBedrockRuntimeClient).toHaveBeenCalledWith( + expect.objectContaining({ + region: "us-east-1", + }), + ) + + // Verify the endpoint property is not present + const clientConfig = mockBedrockRuntimeClient.mock.calls[0][0] + expect(clientConfig).not.toHaveProperty("endpoint") + }) + }) + + // Test Scenario 2: Edge Case Tests + describe("Edge Cases", () => { + it("should handle empty endpoint URL gracefully", () => { + // Create handler with empty endpoint URL but enabled flag + new AwsBedrockHandler({ + apiModelId: "anthropic.claude-3-5-sonnet-20241022-v2:0", + awsAccessKey: "test-access-key", + awsSecretKey: "test-secret-key", + awsRegion: "us-east-1", + awsBedrockEndpoint: "", + awsBedrockEndpointEnabled: true, + }) + + // Verify the client was created without the endpoint (since it's empty) + expect(mockBedrockRuntimeClient).toHaveBeenCalledWith( + expect.objectContaining({ + region: "us-east-1", + }), + ) + + // Verify the endpoint property is not present + const clientConfig = mockBedrockRuntimeClient.mock.calls[0][0] + expect(clientConfig).not.toHaveProperty("endpoint") + }) + + it("should handle undefined endpoint URL gracefully", () => { + // Create handler with undefined endpoint URL but enabled flag + new AwsBedrockHandler({ + apiModelId: "anthropic.claude-3-5-sonnet-20241022-v2:0", + awsAccessKey: "test-access-key", + awsSecretKey: "test-secret-key", + awsRegion: "us-east-1", + awsBedrockEndpoint: undefined, + awsBedrockEndpointEnabled: true, + }) + + // Verify the client was created without the endpoint + expect(mockBedrockRuntimeClient).toHaveBeenCalledWith( + expect.objectContaining({ + region: "us-east-1", + }), + ) + + // Verify the endpoint property is not present + const clientConfig = mockBedrockRuntimeClient.mock.calls[0][0] + expect(clientConfig).not.toHaveProperty("endpoint") + }) + }) + + // Test Scenario 4: Error Handling Tests + describe("Error Handling", () => { + it("should handle invalid endpoint URLs by passing them directly to AWS SDK", () => { + // Create handler with an invalid URL format + new AwsBedrockHandler({ + apiModelId: "anthropic.claude-3-5-sonnet-20241022-v2:0", + awsAccessKey: "test-access-key", + awsSecretKey: "test-secret-key", + awsRegion: "us-east-1", + awsBedrockEndpoint: "invalid-url-format", + awsBedrockEndpointEnabled: true, + }) + + // Verify the client was created with the invalid endpoint + // (AWS SDK will handle the validation/errors) + expect(mockBedrockRuntimeClient).toHaveBeenCalledWith( + expect.objectContaining({ + region: "us-east-1", + endpoint: "invalid-url-format", + }), + ) + }) + }) + + // Test Scenario 5: Persistence Tests + describe("Persistence", () => { + it("should maintain consistent behavior across multiple requests", async () => { + // Create handler with endpoint URL and enabled flag + const handler = new AwsBedrockHandler({ + apiModelId: "anthropic.claude-3-5-sonnet-20241022-v2:0", + awsAccessKey: "test-access-key", + awsSecretKey: "test-secret-key", + awsRegion: "us-east-1", + awsBedrockEndpoint: "https://bedrock-vpc.example.com", + awsBedrockEndpointEnabled: true, + }) + + // Reset mock to clear the constructor call + mockBedrockRuntimeClient.mockClear() + + // Make a request + try { + await handler.completePrompt("Test prompt") + } catch (error) { + // Ignore errors, we're just testing the client configuration + } + + // Verify the client was configured with the endpoint + expect(mockSend).toHaveBeenCalled() + }) + }) +}) diff --git a/webview-ui/src/components/settings/providers/__tests__/Bedrock.test.tsx b/webview-ui/src/components/settings/providers/__tests__/Bedrock.test.tsx index c187137f68..060cbefa3d 100644 --- a/webview-ui/src/components/settings/providers/__tests__/Bedrock.test.tsx +++ b/webview-ui/src/components/settings/providers/__tests__/Bedrock.test.tsx @@ -105,6 +105,7 @@ describe("Bedrock Component", () => { // Initial render with checkbox checked const apiConfiguration: Partial = { awsBedrockEndpoint: "https://example.com", + awsBedrockEndpointEnabled: true, // Need to explicitly set this to true awsUseProfile: true, // Use profile to avoid rendering other text fields } @@ -124,7 +125,239 @@ describe("Bedrock Component", () => { // Text field should now be hidden expect(screen.queryByTestId("vpc-endpoint-input")).not.toBeInTheDocument() - // Should call setApiConfigurationField to clear the endpoint - expect(mockSetApiConfigurationField).toHaveBeenCalledWith("awsBedrockEndpoint", "") + // Should call setApiConfigurationField to update the enabled flag + expect(mockSetApiConfigurationField).toHaveBeenCalledWith("awsBedrockEndpointEnabled", false) + }) + + // Test Scenario 1: Input Validation Test + describe("Input Validation", () => { + it("should accept valid URL formats", () => { + const apiConfiguration: Partial = { + awsBedrockEndpoint: "", + awsBedrockEndpointEnabled: true, + awsUseProfile: true, + } + + render( + , + ) + + // Find the input field + const inputField = screen.getByTestId("vpc-endpoint-input") + expect(inputField).toBeInTheDocument() + + // Test with a valid URL + fireEvent.change(inputField, { target: { value: "https://bedrock.us-east-1.amazonaws.com" } }) + + // Verify the configuration field was updated with the valid URL + expect(mockSetApiConfigurationField).toHaveBeenCalledWith( + "awsBedrockEndpoint", + "https://bedrock.us-east-1.amazonaws.com", + ) + }) + + it("should handle empty URL input", () => { + const apiConfiguration: Partial = { + awsBedrockEndpoint: "https://example.com", + awsBedrockEndpointEnabled: true, + awsUseProfile: true, + } + + render( + , + ) + + // Find the input field + const inputField = screen.getByTestId("vpc-endpoint-input") + + // Clear the field + fireEvent.change(inputField, { target: { value: "" } }) + + // Verify the configuration field was updated with empty string + expect(mockSetApiConfigurationField).toHaveBeenCalledWith("awsBedrockEndpoint", "") + }) + }) + + // Test Scenario 2: Edge Case Tests + describe("Edge Cases", () => { + it("should preserve endpoint URL when toggling checkbox multiple times", () => { + const apiConfiguration: Partial = { + awsBedrockEndpoint: "https://bedrock-vpc.example.com", + awsBedrockEndpointEnabled: true, + awsUseProfile: true, + } + + render( + , + ) + + // Initial state: checkbox checked, URL visible + expect(screen.getByTestId("vpc-endpoint-input")).toBeInTheDocument() + expect(screen.getByTestId("vpc-endpoint-input")).toHaveValue("https://bedrock-vpc.example.com") + + // Uncheck the checkbox + fireEvent.click(screen.getByTestId("checkbox-input-use-custom-vpc-endpoint")) + + // Verify endpoint enabled was set to false + expect(mockSetApiConfigurationField).toHaveBeenCalledWith("awsBedrockEndpointEnabled", false) + + // Check the checkbox again + fireEvent.click(screen.getByTestId("checkbox-input-use-custom-vpc-endpoint")) + + // Verify endpoint enabled was set to true + expect(mockSetApiConfigurationField).toHaveBeenCalledWith("awsBedrockEndpointEnabled", true) + + // Verify the URL field is visible again + expect(screen.getByTestId("vpc-endpoint-input")).toBeInTheDocument() + }) + + it("should handle very long endpoint URLs", () => { + const veryLongUrl = + "https://bedrock-vpc-endpoint-with-a-very-long-name-that-might-cause-issues-in-some-ui-components.region-1.amazonaws.com/api/v1/endpoint" + + const apiConfiguration: Partial = { + awsBedrockEndpoint: veryLongUrl, + awsBedrockEndpointEnabled: true, + awsUseProfile: true, + } + + render( + , + ) + + // Verify the long URL is displayed correctly + expect(screen.getByTestId("vpc-endpoint-input")).toHaveValue(veryLongUrl) + + // Change the URL to something else + fireEvent.change(screen.getByTestId("vpc-endpoint-input"), { + target: { value: "https://shorter-url.com" }, + }) + + // Verify the configuration was updated + expect(mockSetApiConfigurationField).toHaveBeenCalledWith("awsBedrockEndpoint", "https://shorter-url.com") + }) + }) + + // Test Scenario 4: Error Handling Tests + describe("Error Handling", () => { + it("should handle invalid endpoint URLs gracefully", () => { + const apiConfiguration: Partial = { + awsBedrockEndpoint: "", + awsBedrockEndpointEnabled: true, + awsUseProfile: true, + } + + render( + , + ) + + // Find the input field + const inputField = screen.getByTestId("vpc-endpoint-input") + + // Enter an invalid URL (missing protocol) + fireEvent.change(inputField, { target: { value: "invalid-url" } }) + + // The component should still update the configuration + // (URL validation would typically happen at a higher level or when used) + expect(mockSetApiConfigurationField).toHaveBeenCalledWith("awsBedrockEndpoint", "invalid-url") + }) + }) + + // Test Scenario 5: Persistence Tests + describe("Persistence", () => { + it("should initialize with the correct state from apiConfiguration", () => { + // Test with endpoint enabled + const apiConfigurationEnabled: Partial = { + awsBedrockEndpoint: "https://custom-endpoint.aws.com", + awsBedrockEndpointEnabled: true, + awsUseProfile: true, + } + + const { unmount } = render( + , + ) + + // Verify checkbox is checked and endpoint is visible + expect(screen.getByTestId("checkbox-input-use-custom-vpc-endpoint")).toBeChecked() + expect(screen.getByTestId("vpc-endpoint-input")).toBeInTheDocument() + expect(screen.getByTestId("vpc-endpoint-input")).toHaveValue("https://custom-endpoint.aws.com") + + unmount() + + // Test with endpoint disabled + const apiConfigurationDisabled: Partial = { + awsBedrockEndpoint: "https://custom-endpoint.aws.com", + awsBedrockEndpointEnabled: false, + awsUseProfile: true, + } + + render( + , + ) + + // Verify checkbox is unchecked and endpoint is not visible + expect(screen.getByTestId("checkbox-input-use-custom-vpc-endpoint")).not.toBeChecked() + expect(screen.queryByTestId("vpc-endpoint-input")).not.toBeInTheDocument() + }) + + it("should update state when apiConfiguration changes", () => { + // Initial render with endpoint disabled + const apiConfigurationInitial: Partial = { + awsBedrockEndpoint: "https://initial-endpoint.aws.com", + awsBedrockEndpointEnabled: false, + awsUseProfile: true, + } + + const { rerender } = render( + , + ) + + // Verify initial state + expect(screen.getByTestId("checkbox-input-use-custom-vpc-endpoint")).not.toBeChecked() + expect(screen.queryByTestId("vpc-endpoint-input")).not.toBeInTheDocument() + + // Update with new configuration + const apiConfigurationUpdated: Partial = { + awsBedrockEndpoint: "https://updated-endpoint.aws.com", + awsBedrockEndpointEnabled: true, + awsUseProfile: true, + } + + rerender( + , + ) + + // Verify updated state + expect(screen.getByTestId("checkbox-input-use-custom-vpc-endpoint")).toBeChecked() + expect(screen.getByTestId("vpc-endpoint-input")).toBeInTheDocument() + expect(screen.getByTestId("vpc-endpoint-input")).toHaveValue("https://updated-endpoint.aws.com") + }) }) }) From c9f79801041e5b3e5395dc015ed54bbf1c86f0bc Mon Sep 17 00:00:00 2001 From: Kevin White Date: Fri, 23 May 2025 01:54:23 -0600 Subject: [PATCH 11/22] fix: update ApiConfiguration to ProviderSettings in Bedrock tests and regenerate types --- src/exports/roo-code.d.ts | 4 ++++ src/exports/types.ts | 4 ++++ .../settings/providers/__tests__/Bedrock.test.tsx | 6 +++--- 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/src/exports/roo-code.d.ts b/src/exports/roo-code.d.ts index 3a05097320..c24cf41181 100644 --- a/src/exports/roo-code.d.ts +++ b/src/exports/roo-code.d.ts @@ -660,6 +660,8 @@ type IpcMessage = awsProfile?: string | undefined awsUseProfile?: boolean | undefined awsCustomArn?: string | undefined + awsBedrockEndpoint?: string | undefined + awsBedrockEndpointEnabled?: boolean | undefined vertexKeyFile?: string | undefined vertexJsonCredentials?: string | undefined vertexProjectId?: string | undefined @@ -1137,6 +1139,8 @@ type TaskCommand = awsProfile?: string | undefined awsUseProfile?: boolean | undefined awsCustomArn?: string | undefined + awsBedrockEndpoint?: string | undefined + awsBedrockEndpointEnabled?: boolean | undefined vertexKeyFile?: string | undefined vertexJsonCredentials?: string | undefined vertexProjectId?: string | undefined diff --git a/src/exports/types.ts b/src/exports/types.ts index f192bbe052..233d9e3c3d 100644 --- a/src/exports/types.ts +++ b/src/exports/types.ts @@ -674,6 +674,8 @@ type IpcMessage = awsProfile?: string | undefined awsUseProfile?: boolean | undefined awsCustomArn?: string | undefined + awsBedrockEndpoint?: string | undefined + awsBedrockEndpointEnabled?: boolean | undefined vertexKeyFile?: string | undefined vertexJsonCredentials?: string | undefined vertexProjectId?: string | undefined @@ -1153,6 +1155,8 @@ type TaskCommand = awsProfile?: string | undefined awsUseProfile?: boolean | undefined awsCustomArn?: string | undefined + awsBedrockEndpoint?: string | undefined + awsBedrockEndpointEnabled?: boolean | undefined vertexKeyFile?: string | undefined vertexJsonCredentials?: string | undefined vertexProjectId?: string | undefined diff --git a/webview-ui/src/components/settings/providers/__tests__/Bedrock.test.tsx b/webview-ui/src/components/settings/providers/__tests__/Bedrock.test.tsx index 060cbefa3d..b15c24bc45 100644 --- a/webview-ui/src/components/settings/providers/__tests__/Bedrock.test.tsx +++ b/webview-ui/src/components/settings/providers/__tests__/Bedrock.test.tsx @@ -1,7 +1,7 @@ import React from "react" import { render, screen, fireEvent } from "@testing-library/react" import { Bedrock } from "../Bedrock" -import { ApiConfiguration } from "@roo/shared/api" +import { ProviderSettings } from "@roo/shared/api" // Mock the vscrui Checkbox component jest.mock("vscrui", () => ({ @@ -79,7 +79,7 @@ describe("Bedrock Component", () => { it("should show text field when VPC endpoint checkbox is checked", () => { // Initial render with checkbox unchecked - const apiConfiguration: Partial = { + const apiConfiguration: Partial = { awsBedrockEndpoint: "", awsUseProfile: true, // Use profile to avoid rendering other text fields } @@ -103,7 +103,7 @@ describe("Bedrock Component", () => { it("should hide text field when VPC endpoint checkbox is unchecked", () => { // Initial render with checkbox checked - const apiConfiguration: Partial = { + const apiConfiguration: Partial = { awsBedrockEndpoint: "https://example.com", awsBedrockEndpointEnabled: true, // Need to explicitly set this to true awsUseProfile: true, // Use profile to avoid rendering other text fields From eb42c37ad6fd3aeca152ad10c0aadf824f182d0b Mon Sep 17 00:00:00 2001 From: Kevin White Date: Fri, 23 May 2025 01:55:58 -0600 Subject: [PATCH 12/22] fix: update all instances of ApiConfiguration to ProviderSettings in Bedrock tests --- .../providers/__tests__/Bedrock.test.tsx | 40 +++++++++---------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/webview-ui/src/components/settings/providers/__tests__/Bedrock.test.tsx b/webview-ui/src/components/settings/providers/__tests__/Bedrock.test.tsx index b15c24bc45..0eebf5aca8 100644 --- a/webview-ui/src/components/settings/providers/__tests__/Bedrock.test.tsx +++ b/webview-ui/src/components/settings/providers/__tests__/Bedrock.test.tsx @@ -86,7 +86,7 @@ describe("Bedrock Component", () => { render( , ) @@ -111,7 +111,7 @@ describe("Bedrock Component", () => { render( , ) @@ -132,7 +132,7 @@ describe("Bedrock Component", () => { // Test Scenario 1: Input Validation Test describe("Input Validation", () => { it("should accept valid URL formats", () => { - const apiConfiguration: Partial = { + const apiConfiguration: Partial = { awsBedrockEndpoint: "", awsBedrockEndpointEnabled: true, awsUseProfile: true, @@ -140,7 +140,7 @@ describe("Bedrock Component", () => { render( , ) @@ -160,7 +160,7 @@ describe("Bedrock Component", () => { }) it("should handle empty URL input", () => { - const apiConfiguration: Partial = { + const apiConfiguration: Partial = { awsBedrockEndpoint: "https://example.com", awsBedrockEndpointEnabled: true, awsUseProfile: true, @@ -168,7 +168,7 @@ describe("Bedrock Component", () => { render( , ) @@ -187,7 +187,7 @@ describe("Bedrock Component", () => { // Test Scenario 2: Edge Case Tests describe("Edge Cases", () => { it("should preserve endpoint URL when toggling checkbox multiple times", () => { - const apiConfiguration: Partial = { + const apiConfiguration: Partial = { awsBedrockEndpoint: "https://bedrock-vpc.example.com", awsBedrockEndpointEnabled: true, awsUseProfile: true, @@ -195,7 +195,7 @@ describe("Bedrock Component", () => { render( , ) @@ -224,7 +224,7 @@ describe("Bedrock Component", () => { const veryLongUrl = "https://bedrock-vpc-endpoint-with-a-very-long-name-that-might-cause-issues-in-some-ui-components.region-1.amazonaws.com/api/v1/endpoint" - const apiConfiguration: Partial = { + const apiConfiguration: Partial = { awsBedrockEndpoint: veryLongUrl, awsBedrockEndpointEnabled: true, awsUseProfile: true, @@ -232,7 +232,7 @@ describe("Bedrock Component", () => { render( , ) @@ -253,7 +253,7 @@ describe("Bedrock Component", () => { // Test Scenario 4: Error Handling Tests describe("Error Handling", () => { it("should handle invalid endpoint URLs gracefully", () => { - const apiConfiguration: Partial = { + const apiConfiguration: Partial = { awsBedrockEndpoint: "", awsBedrockEndpointEnabled: true, awsUseProfile: true, @@ -261,7 +261,7 @@ describe("Bedrock Component", () => { render( , ) @@ -282,7 +282,7 @@ describe("Bedrock Component", () => { describe("Persistence", () => { it("should initialize with the correct state from apiConfiguration", () => { // Test with endpoint enabled - const apiConfigurationEnabled: Partial = { + const apiConfigurationEnabled: Partial = { awsBedrockEndpoint: "https://custom-endpoint.aws.com", awsBedrockEndpointEnabled: true, awsUseProfile: true, @@ -290,7 +290,7 @@ describe("Bedrock Component", () => { const { unmount } = render( , ) @@ -303,7 +303,7 @@ describe("Bedrock Component", () => { unmount() // Test with endpoint disabled - const apiConfigurationDisabled: Partial = { + const apiConfigurationDisabled: Partial = { awsBedrockEndpoint: "https://custom-endpoint.aws.com", awsBedrockEndpointEnabled: false, awsUseProfile: true, @@ -311,7 +311,7 @@ describe("Bedrock Component", () => { render( , ) @@ -323,7 +323,7 @@ describe("Bedrock Component", () => { it("should update state when apiConfiguration changes", () => { // Initial render with endpoint disabled - const apiConfigurationInitial: Partial = { + const apiConfigurationInitial: Partial = { awsBedrockEndpoint: "https://initial-endpoint.aws.com", awsBedrockEndpointEnabled: false, awsUseProfile: true, @@ -331,7 +331,7 @@ describe("Bedrock Component", () => { const { rerender } = render( , ) @@ -341,7 +341,7 @@ describe("Bedrock Component", () => { expect(screen.queryByTestId("vpc-endpoint-input")).not.toBeInTheDocument() // Update with new configuration - const apiConfigurationUpdated: Partial = { + const apiConfigurationUpdated: Partial = { awsBedrockEndpoint: "https://updated-endpoint.aws.com", awsBedrockEndpointEnabled: true, awsUseProfile: true, @@ -349,7 +349,7 @@ describe("Bedrock Component", () => { rerender( , ) From a74b6fd9d61ba230bba3682c93834a9d16f18416 Mon Sep 17 00:00:00 2001 From: Kevin White Date: Sat, 24 May 2025 17:01:36 -0600 Subject: [PATCH 13/22] Fixed broken unit test --- src/core/config/__tests__/importExport.test.ts | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/core/config/__tests__/importExport.test.ts b/src/core/config/__tests__/importExport.test.ts index 3fe5e97595..f5466c62dc 100644 --- a/src/core/config/__tests__/importExport.test.ts +++ b/src/core/config/__tests__/importExport.test.ts @@ -225,10 +225,8 @@ describe("importExport", () => { customModesManager: mockCustomModesManager, }) - expect(result).toEqual({ - success: false, - error: "Expected property name or '}' in JSON at position 2", - }) + expect(result.success).toBe(false) + expect(result.error).toMatch(/^Expected property name or '}' in JSON at position 2/) expect(fs.readFile).toHaveBeenCalledWith("/mock/path/settings.json", "utf-8") expect(mockProviderSettingsManager.import).not.toHaveBeenCalled() expect(mockContextProxy.setValues).not.toHaveBeenCalled() From 617e68e44c01b20ab5d889f6f5c1962d253b0750 Mon Sep 17 00:00:00 2001 From: Kevin White Date: Sat, 24 May 2025 18:59:32 -0600 Subject: [PATCH 14/22] Add changeset for Bedrock VPC endpoint support --- .changeset/bedrock-vpc-endpoint.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/bedrock-vpc-endpoint.md diff --git a/.changeset/bedrock-vpc-endpoint.md b/.changeset/bedrock-vpc-endpoint.md new file mode 100644 index 0000000000..8249015bb2 --- /dev/null +++ b/.changeset/bedrock-vpc-endpoint.md @@ -0,0 +1,5 @@ +--- +"roo-cline": patch +--- + +Add AWS Bedrock VPC endpoint support, allowing users to connect to Bedrock through private VPC endpoints. This includes UI configuration options, updated types, and comprehensive test coverage. From 7f90298cc999fdcd968a9fca706c2d3b929b679a Mon Sep 17 00:00:00 2001 From: Daniel <57051444+daniel-lxs@users.noreply.github.com> Date: Thu, 29 May 2025 19:00:22 -0500 Subject: [PATCH 15/22] informative placeholder --- webview-ui/src/components/settings/providers/Bedrock.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/webview-ui/src/components/settings/providers/Bedrock.tsx b/webview-ui/src/components/settings/providers/Bedrock.tsx index ea03d42b9e..41bd73a865 100644 --- a/webview-ui/src/components/settings/providers/Bedrock.tsx +++ b/webview-ui/src/components/settings/providers/Bedrock.tsx @@ -141,7 +141,7 @@ export const Bedrock = ({ apiConfiguration, setApiConfigurationField, selectedMo style={{ width: "100%", marginTop: 3, marginBottom: 5 }} type="url" onInput={handleInputChange("awsBedrockEndpoint")} - placeholder="Enter VPC Endpoint URL (optional)" + placeholder="https://vpce-xxx.bedrock.region.vpce.amazonaws.com/" /> )} From fae7a6eb95ded30fbbe24e8f46ae2663ae2dee47 Mon Sep 17 00:00:00 2001 From: Kevin White Date: Fri, 30 May 2025 17:08:32 -0600 Subject: [PATCH 16/22] Bug fixes --- packages/types/src/provider-settings.ts | 4 ++++ .../components/settings/providers/__tests__/Bedrock.test.tsx | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/packages/types/src/provider-settings.ts b/packages/types/src/provider-settings.ts index 7076361ea5..08a328379d 100644 --- a/packages/types/src/provider-settings.ts +++ b/packages/types/src/provider-settings.ts @@ -100,6 +100,8 @@ const bedrockSchema = apiModelIdProviderModelSchema.extend({ awsProfile: z.string().optional(), awsUseProfile: z.boolean().optional(), awsCustomArn: z.string().optional(), + awsBedrockEndpointEnabled: z.boolean().optional(), + awsBedrockEndpoint: z.string().optional(), }) const vertexSchema = apiModelIdProviderModelSchema.extend({ @@ -283,6 +285,8 @@ export const PROVIDER_SETTINGS_KEYS = keysOf()([ "awsProfile", "awsUseProfile", "awsCustomArn", + "awsBedrockEndpointEnabled", + "awsBedrockEndpoint", // Google Vertex "vertexKeyFile", "vertexJsonCredentials", diff --git a/webview-ui/src/components/settings/providers/__tests__/Bedrock.test.tsx b/webview-ui/src/components/settings/providers/__tests__/Bedrock.test.tsx index 0eebf5aca8..69d1c58bc8 100644 --- a/webview-ui/src/components/settings/providers/__tests__/Bedrock.test.tsx +++ b/webview-ui/src/components/settings/providers/__tests__/Bedrock.test.tsx @@ -1,7 +1,7 @@ import React from "react" import { render, screen, fireEvent } from "@testing-library/react" import { Bedrock } from "../Bedrock" -import { ProviderSettings } from "@roo/shared/api" +import { ProviderSettings } from "@roo-code/types" // Mock the vscrui Checkbox component jest.mock("vscrui", () => ({ From 42be6dc77e7b19b714c8a1dbe955be47bbff73e7 Mon Sep 17 00:00:00 2001 From: Kevin White Date: Fri, 30 May 2025 17:58:09 -0600 Subject: [PATCH 17/22] Fixed failing tests --- webview-ui/src/components/settings/providers/Bedrock.tsx | 3 ++- .../settings/providers/__tests__/Bedrock.test.tsx | 6 +++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/webview-ui/src/components/settings/providers/Bedrock.tsx b/webview-ui/src/components/settings/providers/Bedrock.tsx index d61c3974e3..041b80121e 100644 --- a/webview-ui/src/components/settings/providers/Bedrock.tsx +++ b/webview-ui/src/components/settings/providers/Bedrock.tsx @@ -140,7 +140,8 @@ export const Bedrock = ({ apiConfiguration, setApiConfigurationField, selectedMo style={{ width: "100%", marginTop: 3, marginBottom: 5 }} type="url" onInput={handleInputChange("awsBedrockEndpoint")} - placeholder="https://vpce-xxx.bedrock.region.vpce.amazonaws.com/" + placeholder="Enter VPC Endpoint URL (optional)" + data-testid="vpc-endpoint-input" /> )} diff --git a/webview-ui/src/components/settings/providers/__tests__/Bedrock.test.tsx b/webview-ui/src/components/settings/providers/__tests__/Bedrock.test.tsx index 69d1c58bc8..08110e7509 100644 --- a/webview-ui/src/components/settings/providers/__tests__/Bedrock.test.tsx +++ b/webview-ui/src/components/settings/providers/__tests__/Bedrock.test.tsx @@ -20,9 +20,9 @@ jest.mock("vscrui", () => ({ // Mock the VSCodeTextField component jest.mock("@vscode/webview-ui-toolkit/react", () => ({ - VSCodeTextField: ({ children, value, onInput, placeholder, className, style }: any) => { - // Special case for VPC endpoint field - if (placeholder === "Enter VPC Endpoint URL (optional)") { + VSCodeTextField: ({ children, value, onInput, placeholder, className, style, "data-testid": dataTestId }: any) => { + // Special case for VPC endpoint field with data-testid + if (dataTestId === "vpc-endpoint-input") { return (
{children} From f32f14648ab4586577dafe81011576400f3432cc Mon Sep 17 00:00:00 2001 From: Kevin White Date: Fri, 30 May 2025 18:10:47 -0600 Subject: [PATCH 18/22] Add example URLs to Bedrock VPC endpoint section and update tests --- .../components/settings/providers/Bedrock.tsx | 23 +++++--- .../providers/__tests__/Bedrock.test.tsx | 54 +++++++++++++++++++ 2 files changed, 69 insertions(+), 8 deletions(-) diff --git a/webview-ui/src/components/settings/providers/Bedrock.tsx b/webview-ui/src/components/settings/providers/Bedrock.tsx index 041b80121e..735ca5af17 100644 --- a/webview-ui/src/components/settings/providers/Bedrock.tsx +++ b/webview-ui/src/components/settings/providers/Bedrock.tsx @@ -135,14 +135,21 @@ export const Bedrock = ({ apiConfiguration, setApiConfigurationField, selectedMo Use custom VPC endpoint {awsEndpointSelected && ( - + <> + +
+ Examples: +
• https://vpce-xxx.bedrock.region.vpce.amazonaws.com/
+
• https://gateway.my-company.com/route/app/bedrock
+
+ )} ) diff --git a/webview-ui/src/components/settings/providers/__tests__/Bedrock.test.tsx b/webview-ui/src/components/settings/providers/__tests__/Bedrock.test.tsx index 08110e7509..031a96abce 100644 --- a/webview-ui/src/components/settings/providers/__tests__/Bedrock.test.tsx +++ b/webview-ui/src/components/settings/providers/__tests__/Bedrock.test.tsx @@ -250,6 +250,60 @@ describe("Bedrock Component", () => { }) }) + // Test Scenario 3: UI Elements Tests + describe("UI Elements", () => { + it("should display example URLs when VPC endpoint checkbox is checked", () => { + const apiConfiguration: Partial = { + awsBedrockEndpoint: "https://example.com", + awsBedrockEndpointEnabled: true, + awsUseProfile: true, + } + + render( + , + ) + + // Check that the VPC endpoint input is visible + expect(screen.getByTestId("vpc-endpoint-input")).toBeInTheDocument() + + // Check for the example URLs section + // Since we don't have a specific testid for the examples section, + // we'll check for the text content + expect(screen.getByText("Examples:")).toBeInTheDocument() + expect(screen.getByText("• https://vpce-xxx.bedrock.region.vpce.amazonaws.com/")).toBeInTheDocument() + expect(screen.getByText("• https://gateway.my-company.com/route/app/bedrock")).toBeInTheDocument() + }) + + it("should hide example URLs when VPC endpoint checkbox is unchecked", () => { + const apiConfiguration: Partial = { + awsBedrockEndpoint: "https://example.com", + awsBedrockEndpointEnabled: true, + awsUseProfile: true, + } + + render( + , + ) + + // Initially the examples should be visible + expect(screen.getByText("Examples:")).toBeInTheDocument() + + // Uncheck the VPC endpoint checkbox + fireEvent.click(screen.getByTestId("checkbox-input-use-custom-vpc-endpoint")) + + // Now the examples should be hidden + expect(screen.queryByText("Examples:")).not.toBeInTheDocument() + expect(screen.queryByText("• https://vpce-xxx.bedrock.region.vpce.amazonaws.com/")).not.toBeInTheDocument() + expect(screen.queryByText("• https://gateway.my-company.com/route/app/bedrock")).not.toBeInTheDocument() + }) + }) + // Test Scenario 4: Error Handling Tests describe("Error Handling", () => { it("should handle invalid endpoint URLs gracefully", () => { From 01c7d2f07a103c29c3787659d95931cd57c1952c Mon Sep 17 00:00:00 2001 From: Kevin White Date: Fri, 30 May 2025 18:44:56 -0600 Subject: [PATCH 19/22] Fix truncated test assertion in Bedrock.test.tsx that was breaking the UI --- .../components/settings/providers/__tests__/Bedrock.test.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/webview-ui/src/components/settings/providers/__tests__/Bedrock.test.tsx b/webview-ui/src/components/settings/providers/__tests__/Bedrock.test.tsx index 031a96abce..1a4c5e462e 100644 --- a/webview-ui/src/components/settings/providers/__tests__/Bedrock.test.tsx +++ b/webview-ui/src/components/settings/providers/__tests__/Bedrock.test.tsx @@ -6,12 +6,12 @@ import { ProviderSettings } from "@roo-code/types" // Mock the vscrui Checkbox component jest.mock("vscrui", () => ({ Checkbox: ({ children, checked, onChange }: any) => ( -