@@ -18,6 +18,22 @@ vi.mock("@aws-sdk/credential-providers", () => {
1818 return { fromIni : mockFromIni }
1919} )
2020
21+ vi . mock ( "../../../utils/networkProxy" , ( ) => ( {
22+ getSystemProxyUrl : vi . fn ( ) . mockReturnValue ( undefined ) ,
23+ } ) )
24+
25+ vi . mock ( "@smithy/node-http-handler" , ( ) => ( {
26+ NodeHttpHandler : vi . fn ( ) ,
27+ } ) )
28+
29+ vi . mock ( "http-proxy-agent" , ( ) => ( {
30+ HttpProxyAgent : vi . fn ( ) ,
31+ } ) )
32+
33+ vi . mock ( "https-proxy-agent" , ( ) => ( {
34+ HttpsProxyAgent : vi . fn ( ) ,
35+ } ) )
36+
2137// Mock BedrockRuntimeClient and ConverseStreamCommand
2238vi . mock ( "@aws-sdk/client-bedrock-runtime" , ( ) => {
2339 const mockSend = vi . fn ( ) . mockResolvedValue ( {
@@ -46,10 +62,18 @@ import {
4662} from "@roo-code/types"
4763
4864import type { Anthropic } from "@anthropic-ai/sdk"
65+ import { getSystemProxyUrl } from "../../../utils/networkProxy"
66+ import { NodeHttpHandler } from "@smithy/node-http-handler"
67+ import { HttpProxyAgent } from "http-proxy-agent"
68+ import { HttpsProxyAgent } from "https-proxy-agent"
4969
5070// Get access to the mocked functions
5171const mockConverseStreamCommand = vi . mocked ( ConverseStreamCommand )
5272const mockBedrockRuntimeClient = vi . mocked ( BedrockRuntimeClient )
73+ const mockGetSystemProxyUrl = vi . mocked ( getSystemProxyUrl )
74+ const mockNodeHttpHandler = vi . mocked ( NodeHttpHandler )
75+ const mockHttpProxyAgent = vi . mocked ( HttpProxyAgent )
76+ const mockHttpsProxyAgent = vi . mocked ( HttpsProxyAgent )
5377
5478describe ( "AwsBedrockHandler" , ( ) => {
5579 let handler : AwsBedrockHandler
@@ -118,6 +142,95 @@ describe("AwsBedrockHandler", () => {
118142 } )
119143 } )
120144
145+ describe ( "proxy configuration" , ( ) => {
146+ afterEach ( ( ) => {
147+ mockGetSystemProxyUrl . mockReturnValue ( undefined )
148+ } )
149+
150+ it ( "should configure NodeHttpHandler with HttpProxyAgent and HttpsProxyAgent when proxy URL is set" , ( ) => {
151+ mockGetSystemProxyUrl . mockReturnValue ( "http://proxy.corp.local:3128" )
152+
153+ new AwsBedrockHandler ( {
154+ apiModelId : "anthropic.claude-3-5-sonnet-20241022-v2:0" ,
155+ awsAccessKey : "test-access-key" ,
156+ awsSecretKey : "test-secret-key" ,
157+ awsRegion : "us-east-1" ,
158+ } )
159+
160+ // Verify both proxy agents were created with the correct URL
161+ expect ( mockHttpProxyAgent ) . toHaveBeenCalledWith ( "http://proxy.corp.local:3128" )
162+ expect ( mockHttpsProxyAgent ) . toHaveBeenCalledWith ( "http://proxy.corp.local:3128" )
163+
164+ // Verify NodeHttpHandler was created with both agents
165+ expect ( mockNodeHttpHandler ) . toHaveBeenCalledWith (
166+ expect . objectContaining ( {
167+ httpAgent : expect . anything ( ) ,
168+ httpsAgent : expect . anything ( ) ,
169+ requestTimeout : 0 ,
170+ } ) ,
171+ )
172+
173+ // Verify requestHandler was set on BedrockRuntimeClient config
174+ expect ( mockBedrockRuntimeClient ) . toHaveBeenLastCalledWith (
175+ expect . objectContaining ( { requestHandler : expect . anything ( ) } ) ,
176+ )
177+ } )
178+
179+ it ( "should not create a proxy requestHandler when no proxy is configured" , ( ) => {
180+ new AwsBedrockHandler ( {
181+ apiModelId : "anthropic.claude-3-5-sonnet-20241022-v2:0" ,
182+ awsAccessKey : "test-access-key" ,
183+ awsSecretKey : "test-secret-key" ,
184+ awsRegion : "us-east-1" ,
185+ } )
186+
187+ expect ( mockNodeHttpHandler ) . not . toHaveBeenCalled ( )
188+ expect ( mockBedrockRuntimeClient . mock . lastCall ?. [ 0 ] ?. requestHandler ) . toBeUndefined ( )
189+ } )
190+
191+ it ( "should apply proxy for API key authentication" , ( ) => {
192+ mockGetSystemProxyUrl . mockReturnValue ( "http://proxy.corp.local:3128" )
193+
194+ new AwsBedrockHandler ( {
195+ apiModelId : "anthropic.claude-3-5-sonnet-20241022-v2:0" ,
196+ awsUseApiKey : true ,
197+ awsApiKey : "test-api-key" ,
198+ awsRegion : "us-east-1" ,
199+ } )
200+
201+ expect ( mockNodeHttpHandler ) . toHaveBeenCalledWith (
202+ expect . objectContaining ( {
203+ httpsAgent : expect . anything ( ) ,
204+ requestTimeout : 0 ,
205+ } ) ,
206+ )
207+ } )
208+
209+ it ( "should pass a custom endpoint to getSystemProxyUrl for NO_PROXY matching" , ( ) => {
210+ new AwsBedrockHandler ( {
211+ apiModelId : "anthropic.claude-3-5-sonnet-20241022-v2:0" ,
212+ awsAccessKey : "test-access-key" ,
213+ awsSecretKey : "test-secret-key" ,
214+ awsRegion : "us-east-1" ,
215+ awsBedrockEndpoint : "https://bedrock.vpce.internal" ,
216+ awsBedrockEndpointEnabled : true ,
217+ } )
218+
219+ expect ( mockGetSystemProxyUrl ) . toHaveBeenCalledWith ( "https://bedrock.vpce.internal" )
220+ } )
221+
222+ it ( "should pass undefined to getSystemProxyUrl when no custom endpoint is set" , ( ) => {
223+ new AwsBedrockHandler ( {
224+ apiModelId : "anthropic.claude-3-5-sonnet-20241022-v2:0" ,
225+ awsAccessKey : "test-access-key" ,
226+ awsSecretKey : "test-secret-key" ,
227+ awsRegion : "us-east-1" ,
228+ } )
229+
230+ expect ( mockGetSystemProxyUrl ) . toHaveBeenCalledWith ( undefined )
231+ } )
232+ } )
233+
121234 describe ( "region mapping and cross-region inference" , ( ) => {
122235 describe ( "getPrefixForRegion" , ( ) => {
123236 it ( "should return correct prefix for US regions" , ( ) => {
0 commit comments