@@ -21,6 +21,23 @@ impl fmt::Display for VerbosityProfile {
2121 }
2222}
2323
24+ /// Configuration for the AI Gateway feature in tests.
25+ #[ derive( Clone , Default , TypedBuilder ) ]
26+ pub struct AiGatewayConfig {
27+ /// Whether the AI gateway is enabled.
28+ #[ builder( default = false ) ]
29+ pub enabled : bool ,
30+ /// Optional API key for gateway-level authentication.
31+ #[ builder( default , setter( into) ) ]
32+ pub gateway_api_key : Option < String > ,
33+ /// Custom endpoint for the OpenAI provider (for mock server).
34+ #[ builder( default , setter( into) ) ]
35+ pub openai_endpoint : Option < String > ,
36+ /// API key for OpenAI provider.
37+ #[ builder( default , setter( into) ) ]
38+ pub openai_api_key : Option < String > ,
39+ }
40+
2441#[ derive( TypedBuilder ) ]
2542pub struct DgwConfig {
2643 #[ builder( default , setter( into) ) ]
@@ -31,6 +48,12 @@ pub struct DgwConfig {
3148 disable_token_validation : bool ,
3249 #[ builder( default = VerbosityProfile :: DEFAULT ) ]
3350 verbosity_profile : VerbosityProfile ,
51+ /// AI gateway configuration (requires enable_unstable: true to work).
52+ #[ builder( default , setter( into) ) ]
53+ ai_gateway : Option < AiGatewayConfig > ,
54+ /// Enable unstable features (required for AI gateway).
55+ #[ builder( default = false ) ]
56+ enable_unstable : bool ,
3457}
3558
3659fn find_unused_port ( ) -> u16 {
@@ -60,6 +83,8 @@ impl DgwConfigHandle {
6083 http_port,
6184 disable_token_validation,
6285 verbosity_profile,
86+ ai_gateway,
87+ enable_unstable,
6388 } = config;
6489
6590 let tempdir = tempfile:: tempdir ( ) . context ( "create tempdir" ) ?;
@@ -68,26 +93,71 @@ impl DgwConfigHandle {
6893 let tcp_port = tcp_port. unwrap_or_else ( find_unused_port) ;
6994 let http_port = http_port. unwrap_or_else ( find_unused_port) ;
7095
96+ // Build AI gateway config JSON if provided.
97+ let ai_gateway_json = if let Some ( ai_config) = ai_gateway {
98+ let gateway_api_key_json = ai_config
99+ . gateway_api_key
100+ . map ( |k| format ! ( r#""GatewayApiKey": "{k}","# ) )
101+ . unwrap_or_default ( ) ;
102+
103+ let openai_provider_json = if ai_config. openai_endpoint . is_some ( ) || ai_config. openai_api_key . is_some ( ) {
104+ let endpoint_json = ai_config
105+ . openai_endpoint
106+ . map ( |e| format ! ( r#""Endpoint": "{e}""# ) )
107+ . unwrap_or_default ( ) ;
108+ let api_key_json = ai_config
109+ . openai_api_key
110+ . map ( |k| format ! ( r#""ApiKey": "{k}""# ) )
111+ . unwrap_or_default ( ) ;
112+ let comma = if !endpoint_json. is_empty ( ) && !api_key_json. is_empty ( ) {
113+ ","
114+ } else {
115+ ""
116+ } ;
117+ format ! (
118+ r#""Providers": {{
119+ "Openai": {{ {endpoint_json}{comma}{api_key_json} }}
120+ }},"#
121+ )
122+ } else {
123+ String :: new ( )
124+ } ;
125+
126+ format ! (
127+ r#",
128+ "AiGateway": {{
129+ "Enabled": {},
130+ {gateway_api_key_json}
131+ {openai_provider_json}
132+ "RequestTimeoutSecs": 30
133+ }}"# ,
134+ ai_config. enabled
135+ )
136+ } else {
137+ String :: new ( )
138+ } ;
139+
71140 let config = format ! (
72- "{{
73- \ " ProvisionerPublicKeyData\ " : {{
74- \ " Value\ " : \ " mMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4vuqLOkl1pWobt6su1XO9VskgCAwevEGs6kkNjJQBwkGnPKYLmNF1E/af1yCocfVn/OnPf9e4x+lXVyZ6LMDJxFxu+axdgOq3Ld392J1iAEbfvwlyRFnEXFOJNyylqg3bY6LvnWHL/XZczVdMD9xYfq2sO9bg3xjRW4s7r9EEYOFjqVT3VFznH9iWJVtcSEKukmS/3uKoO6lGhacvu0HgjXXdgq0R8zvR4XRJ9Fcnf0f9Ypoc+i6L80NVjrRCeVOH+Ld/2fA9bocpfLarcVqG3RjS+qgOtpyCc0jWVFF4zaGQ7LUDFkEIYILkICeMMn2ll29hmZNzsJzZJ9s6NocgQIDAQAB\ "
141+ r# "{{
142+ "ProvisionerPublicKeyData": {{
143+ "Value": "mMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4vuqLOkl1pWobt6su1XO9VskgCAwevEGs6kkNjJQBwkGnPKYLmNF1E/af1yCocfVn/OnPf9e4x+lXVyZ6LMDJxFxu+axdgOq3Ld392J1iAEbfvwlyRFnEXFOJNyylqg3bY6LvnWHL/XZczVdMD9xYfq2sO9bg3xjRW4s7r9EEYOFjqVT3VFznH9iWJVtcSEKukmS/3uKoO6lGhacvu0HgjXXdgq0R8zvR4XRJ9Fcnf0f9Ypoc+i6L80NVjrRCeVOH+Ld/2fA9bocpfLarcVqG3RjS+qgOtpyCc0jWVFF4zaGQ7LUDFkEIYILkICeMMn2ll29hmZNzsJzZJ9s6NocgQIDAQAB"
75144 }},
76- \ " Listeners\ " : [
145+ "Listeners": [
77146 {{
78- \ " InternalUrl\ " : \ " tcp://127.0.0.1:{tcp_port}\ " ,
79- \ " ExternalUrl\ " : \ " tcp://127.0.0.1:{tcp_port}\ "
147+ "InternalUrl": "tcp://127.0.0.1:{tcp_port}",
148+ "ExternalUrl": "tcp://127.0.0.1:{tcp_port}"
80149 }},
81150 {{
82- \ " InternalUrl\ " : \ " http://127.0.0.1:{http_port}\ " ,
83- \ " ExternalUrl\ " : \ " http://127.0.0.1:{http_port}\ "
151+ "InternalUrl": "http://127.0.0.1:{http_port}",
152+ "ExternalUrl": "http://127.0.0.1:{http_port}"
84153 }}
85154 ],
86- \" VerbosityProfile\" : \" {verbosity_profile}\" ,
87- \" __debug__\" : {{
88- \" disable_token_validation\" : {disable_token_validation}
89- }}
90- }}"
155+ "VerbosityProfile": "{verbosity_profile}",
156+ "__debug__": {{
157+ "disable_token_validation": {disable_token_validation},
158+ "enable_unstable": {enable_unstable}
159+ }}{ai_gateway_json}
160+ }}"#
91161 ) ;
92162
93163 std:: fs:: write ( & config_path, config) . with_context ( || format ! ( "write config into {}" , config_path. display( ) ) ) ?;
0 commit comments