mirror of
https://github.com/RooVetGit/Roo-Code.git
synced 2026-09-05 08:10:14 +00:00
feat: add custom region input support for AWS Bedrock provider
- Add awsCustomRegion field to ProviderSettings schema - Update BEDROCK_REGIONS to include "Custom region..." option - Modify Bedrock UI component to support custom region input - Add conditional UI similar to VPC endpoint pattern - Handle state management for switching between standard and custom regions - Preserve existing validation logic and maintain backward compatibility - Add comprehensive tests for custom region functionality Fixes #5923
This commit is contained in:
parent
b6bded9818
commit
24d2adb298
4 changed files with 250 additions and 2 deletions
|
|
@ -107,6 +107,7 @@ const bedrockSchema = apiModelIdProviderModelSchema.extend({
|
|||
awsSecretKey: z.string().optional(),
|
||||
awsSessionToken: z.string().optional(),
|
||||
awsRegion: z.string().optional(),
|
||||
awsCustomRegion: z.string().optional(),
|
||||
awsUseCrossRegionInference: z.boolean().optional(),
|
||||
awsUsePromptCache: z.boolean().optional(),
|
||||
awsProfile: z.string().optional(),
|
||||
|
|
|
|||
|
|
@ -405,4 +405,10 @@ export const BEDROCK_REGIONS = [
|
|||
{ value: "sa-east-1", label: "sa-east-1" },
|
||||
{ value: "us-gov-east-1", label: "us-gov-east-1" },
|
||||
{ value: "us-gov-west-1", label: "us-gov-west-1" },
|
||||
].sort((a, b) => a.value.localeCompare(b.value))
|
||||
{ value: "custom", label: "Custom region..." },
|
||||
].sort((a, b) => {
|
||||
// Keep "Custom region..." at the end
|
||||
if (a.value === "custom") return 1
|
||||
if (b.value === "custom") return -1
|
||||
return a.value.localeCompare(b.value)
|
||||
})
|
||||
|
|
|
|||
|
|
@ -18,12 +18,18 @@ type BedrockProps = {
|
|||
export const Bedrock = ({ apiConfiguration, setApiConfigurationField, selectedModelInfo }: BedrockProps) => {
|
||||
const { t } = useAppTranslation()
|
||||
const [awsEndpointSelected, setAwsEndpointSelected] = useState(!!apiConfiguration?.awsBedrockEndpointEnabled)
|
||||
const [customRegionSelected, setCustomRegionSelected] = useState(apiConfiguration?.awsRegion === "custom")
|
||||
|
||||
// Update the endpoint enabled state when the configuration changes
|
||||
useEffect(() => {
|
||||
setAwsEndpointSelected(!!apiConfiguration?.awsBedrockEndpointEnabled)
|
||||
}, [apiConfiguration?.awsBedrockEndpointEnabled])
|
||||
|
||||
// Update the custom region state when the configuration changes
|
||||
useEffect(() => {
|
||||
setCustomRegionSelected(apiConfiguration?.awsRegion === "custom")
|
||||
}, [apiConfiguration?.awsRegion])
|
||||
|
||||
const handleInputChange = useCallback(
|
||||
<K extends keyof ProviderSettings, E>(
|
||||
field: K,
|
||||
|
|
@ -89,7 +95,14 @@ export const Bedrock = ({ apiConfiguration, setApiConfigurationField, selectedMo
|
|||
<label className="block font-medium mb-1">{t("settings:providers.awsRegion")}</label>
|
||||
<Select
|
||||
value={apiConfiguration?.awsRegion || ""}
|
||||
onValueChange={(value) => setApiConfigurationField("awsRegion", value)}>
|
||||
onValueChange={(value) => {
|
||||
setApiConfigurationField("awsRegion", value)
|
||||
setCustomRegionSelected(value === "custom")
|
||||
// Clear custom region when switching to a standard region
|
||||
if (value !== "custom") {
|
||||
setApiConfigurationField("awsCustomRegion", "")
|
||||
}
|
||||
}}>
|
||||
<SelectTrigger className="w-full">
|
||||
<SelectValue placeholder={t("settings:common.select")} />
|
||||
</SelectTrigger>
|
||||
|
|
@ -102,6 +115,23 @@ export const Bedrock = ({ apiConfiguration, setApiConfigurationField, selectedMo
|
|||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
{customRegionSelected && (
|
||||
<>
|
||||
<VSCodeTextField
|
||||
value={apiConfiguration?.awsCustomRegion || ""}
|
||||
style={{ width: "100%", marginTop: 3, marginBottom: 5 }}
|
||||
onInput={handleInputChange("awsCustomRegion")}
|
||||
placeholder={t("settings:placeholders.customRegion")}
|
||||
data-testid="custom-region-input"
|
||||
/>
|
||||
<div className="text-sm text-vscode-descriptionForeground ml-6 mt-1 mb-3">
|
||||
{t("settings:providers.awsCustomRegion.examples")}
|
||||
<div className="ml-2">• us-west-3</div>
|
||||
<div className="ml-2">• eu-central-3</div>
|
||||
<div className="ml-2">• ap-southeast-3</div>
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
<Checkbox
|
||||
checked={apiConfiguration?.awsUseCrossRegionInference || false}
|
||||
onChange={handleInputChange("awsUseCrossRegionInference", noTransform)}>
|
||||
|
|
|
|||
|
|
@ -425,4 +425,215 @@ describe("Bedrock Component", () => {
|
|||
expect(screen.getByTestId("vpc-endpoint-input")).toHaveValue("https://updated-endpoint.aws.com")
|
||||
})
|
||||
})
|
||||
|
||||
// Test Scenario 6: Custom Region Tests
|
||||
describe("Custom Region", () => {
|
||||
it("should show custom region input when 'Custom region...' is selected", () => {
|
||||
const apiConfiguration: Partial<ProviderSettings> = {
|
||||
awsRegion: "",
|
||||
awsUseProfile: true,
|
||||
}
|
||||
|
||||
render(
|
||||
<Bedrock
|
||||
apiConfiguration={apiConfiguration as ProviderSettings}
|
||||
setApiConfigurationField={mockSetApiConfigurationField}
|
||||
/>,
|
||||
)
|
||||
|
||||
// Custom region input should not be visible initially
|
||||
expect(screen.queryByTestId("custom-region-input")).not.toBeInTheDocument()
|
||||
|
||||
// Mock the Select component to simulate selecting "custom"
|
||||
// Since we're mocking the Select component, we need to simulate the onValueChange call
|
||||
const selectComponent = screen.getByRole("combobox", { hidden: true })
|
||||
if (selectComponent) {
|
||||
// Simulate selecting "custom" region
|
||||
const onValueChange = (selectComponent as any).onValueChange || (() => {})
|
||||
onValueChange("custom")
|
||||
}
|
||||
|
||||
// Verify that setApiConfigurationField was called with "custom"
|
||||
expect(mockSetApiConfigurationField).toHaveBeenCalledWith("awsRegion", "custom")
|
||||
})
|
||||
|
||||
it("should hide custom region input when switching from custom to standard region", () => {
|
||||
const apiConfiguration: Partial<ProviderSettings> = {
|
||||
awsRegion: "custom",
|
||||
awsCustomRegion: "us-west-3",
|
||||
awsUseProfile: true,
|
||||
}
|
||||
|
||||
render(
|
||||
<Bedrock
|
||||
apiConfiguration={apiConfiguration as ProviderSettings}
|
||||
setApiConfigurationField={mockSetApiConfigurationField}
|
||||
/>,
|
||||
)
|
||||
|
||||
// Custom region input should be visible initially
|
||||
expect(screen.getByTestId("custom-region-input")).toBeInTheDocument()
|
||||
expect(screen.getByTestId("custom-region-input")).toHaveValue("us-west-3")
|
||||
|
||||
// Mock selecting a standard region
|
||||
const selectComponent = screen.getByRole("combobox", { hidden: true })
|
||||
if (selectComponent) {
|
||||
const onValueChange = (selectComponent as any).onValueChange || (() => {})
|
||||
onValueChange("us-east-1")
|
||||
}
|
||||
|
||||
// Verify that both awsRegion and awsCustomRegion were updated
|
||||
expect(mockSetApiConfigurationField).toHaveBeenCalledWith("awsRegion", "us-east-1")
|
||||
expect(mockSetApiConfigurationField).toHaveBeenCalledWith("awsCustomRegion", "")
|
||||
})
|
||||
|
||||
it("should handle custom region input changes", () => {
|
||||
const apiConfiguration: Partial<ProviderSettings> = {
|
||||
awsRegion: "custom",
|
||||
awsCustomRegion: "",
|
||||
awsUseProfile: true,
|
||||
}
|
||||
|
||||
render(
|
||||
<Bedrock
|
||||
apiConfiguration={apiConfiguration as ProviderSettings}
|
||||
setApiConfigurationField={mockSetApiConfigurationField}
|
||||
/>,
|
||||
)
|
||||
|
||||
// Find the custom region input field
|
||||
const customRegionInput = screen.getByTestId("custom-region-input")
|
||||
expect(customRegionInput).toBeInTheDocument()
|
||||
|
||||
// Enter a custom region
|
||||
fireEvent.change(customRegionInput, { target: { value: "us-west-3" } })
|
||||
|
||||
// Verify the configuration field was updated
|
||||
expect(mockSetApiConfigurationField).toHaveBeenCalledWith("awsCustomRegion", "us-west-3")
|
||||
})
|
||||
|
||||
it("should display example regions when custom region is selected", () => {
|
||||
const apiConfiguration: Partial<ProviderSettings> = {
|
||||
awsRegion: "custom",
|
||||
awsCustomRegion: "us-west-3",
|
||||
awsUseProfile: true,
|
||||
}
|
||||
|
||||
render(
|
||||
<Bedrock
|
||||
apiConfiguration={apiConfiguration as ProviderSettings}
|
||||
setApiConfigurationField={mockSetApiConfigurationField}
|
||||
/>,
|
||||
)
|
||||
|
||||
// Check that the custom region input is visible
|
||||
expect(screen.getByTestId("custom-region-input")).toBeInTheDocument()
|
||||
|
||||
// Check for the example regions section
|
||||
expect(screen.getByText("settings:providers.awsCustomRegion.examples")).toBeInTheDocument()
|
||||
expect(screen.getByText("• us-west-3")).toBeInTheDocument()
|
||||
expect(screen.getByText("• eu-central-3")).toBeInTheDocument()
|
||||
expect(screen.getByText("• ap-southeast-3")).toBeInTheDocument()
|
||||
})
|
||||
|
||||
it("should preserve custom region value when toggling between custom and standard regions", () => {
|
||||
const apiConfiguration: Partial<ProviderSettings> = {
|
||||
awsRegion: "custom",
|
||||
awsCustomRegion: "us-west-3",
|
||||
awsUseProfile: true,
|
||||
}
|
||||
|
||||
const { rerender } = render(
|
||||
<Bedrock
|
||||
apiConfiguration={apiConfiguration as ProviderSettings}
|
||||
setApiConfigurationField={mockSetApiConfigurationField}
|
||||
/>,
|
||||
)
|
||||
|
||||
// Initial state: custom region selected with value
|
||||
expect(screen.getByTestId("custom-region-input")).toBeInTheDocument()
|
||||
expect(screen.getByTestId("custom-region-input")).toHaveValue("us-west-3")
|
||||
|
||||
// Switch to standard region
|
||||
const updatedConfig: Partial<ProviderSettings> = {
|
||||
awsRegion: "us-east-1",
|
||||
awsCustomRegion: "", // This would be cleared by the component logic
|
||||
awsUseProfile: true,
|
||||
}
|
||||
|
||||
rerender(
|
||||
<Bedrock
|
||||
apiConfiguration={updatedConfig as ProviderSettings}
|
||||
setApiConfigurationField={mockSetApiConfigurationField}
|
||||
/>,
|
||||
)
|
||||
|
||||
// Custom region input should be hidden
|
||||
expect(screen.queryByTestId("custom-region-input")).not.toBeInTheDocument()
|
||||
|
||||
// Switch back to custom region with preserved value
|
||||
const backToCustomConfig: Partial<ProviderSettings> = {
|
||||
awsRegion: "custom",
|
||||
awsCustomRegion: "us-west-3", // Value preserved in parent state
|
||||
awsUseProfile: true,
|
||||
}
|
||||
|
||||
rerender(
|
||||
<Bedrock
|
||||
apiConfiguration={backToCustomConfig as ProviderSettings}
|
||||
setApiConfigurationField={mockSetApiConfigurationField}
|
||||
/>,
|
||||
)
|
||||
|
||||
// Custom region input should be visible again with preserved value
|
||||
expect(screen.getByTestId("custom-region-input")).toBeInTheDocument()
|
||||
expect(screen.getByTestId("custom-region-input")).toHaveValue("us-west-3")
|
||||
})
|
||||
|
||||
it("should handle empty custom region input", () => {
|
||||
const apiConfiguration: Partial<ProviderSettings> = {
|
||||
awsRegion: "custom",
|
||||
awsCustomRegion: "us-west-3",
|
||||
awsUseProfile: true,
|
||||
}
|
||||
|
||||
render(
|
||||
<Bedrock
|
||||
apiConfiguration={apiConfiguration as ProviderSettings}
|
||||
setApiConfigurationField={mockSetApiConfigurationField}
|
||||
/>,
|
||||
)
|
||||
|
||||
// Find the custom region input field
|
||||
const customRegionInput = screen.getByTestId("custom-region-input")
|
||||
|
||||
// Clear the field
|
||||
fireEvent.change(customRegionInput, { target: { value: "" } })
|
||||
|
||||
// Verify the configuration field was updated with empty string
|
||||
expect(mockSetApiConfigurationField).toHaveBeenCalledWith("awsCustomRegion", "")
|
||||
})
|
||||
|
||||
it("should initialize with correct state when custom region is pre-selected", () => {
|
||||
const apiConfiguration: Partial<ProviderSettings> = {
|
||||
awsRegion: "custom",
|
||||
awsCustomRegion: "eu-central-3",
|
||||
awsUseProfile: true,
|
||||
}
|
||||
|
||||
render(
|
||||
<Bedrock
|
||||
apiConfiguration={apiConfiguration as ProviderSettings}
|
||||
setApiConfigurationField={mockSetApiConfigurationField}
|
||||
/>,
|
||||
)
|
||||
|
||||
// Verify custom region input is visible and has correct value
|
||||
expect(screen.getByTestId("custom-region-input")).toBeInTheDocument()
|
||||
expect(screen.getByTestId("custom-region-input")).toHaveValue("eu-central-3")
|
||||
|
||||
// Verify examples are shown
|
||||
expect(screen.getByText("settings:providers.awsCustomRegion.examples")).toBeInTheDocument()
|
||||
})
|
||||
})
|
||||
})
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue