@@ -61,6 +61,8 @@ pub enum OpenAIClientProviderVariant {
6161 Ollama ,
6262 /// The Azure client provider variant
6363 Azure ,
64+ /// The OpenAI Responses API variant
65+ Responses ,
6466 /// The generic client provider variant
6567 Generic ,
6668}
@@ -93,6 +95,7 @@ impl std::fmt::Display for OpenAIClientProviderVariant {
9395 OpenAIClientProviderVariant :: Base => write ! ( f, "openai" ) ,
9496 OpenAIClientProviderVariant :: Ollama => write ! ( f, "ollama" ) ,
9597 OpenAIClientProviderVariant :: Azure => write ! ( f, "azure-openai" ) ,
98+ OpenAIClientProviderVariant :: Responses => write ! ( f, "openai-responses" ) ,
9699 OpenAIClientProviderVariant :: Generic => write ! ( f, "openai-generic" ) ,
97100 }
98101 }
@@ -117,6 +120,9 @@ impl std::str::FromStr for ClientProvider {
117120 "openai-generic" => Ok ( ClientProvider :: OpenAI ( OpenAIClientProviderVariant :: Generic ) ) ,
118121 "azure-openai" => Ok ( ClientProvider :: OpenAI ( OpenAIClientProviderVariant :: Azure ) ) ,
119122 "baml-azure-chat" => Ok ( ClientProvider :: OpenAI ( OpenAIClientProviderVariant :: Azure ) ) ,
123+ "openai-responses" => Ok ( ClientProvider :: OpenAI (
124+ OpenAIClientProviderVariant :: Responses ,
125+ ) ) ,
120126 "baml-ollama-chat" => Ok ( ClientProvider :: OpenAI ( OpenAIClientProviderVariant :: Ollama ) ) ,
121127 "ollama" => Ok ( ClientProvider :: OpenAI ( OpenAIClientProviderVariant :: Ollama ) ) ,
122128 "anthropic" => Ok ( ClientProvider :: Anthropic ) ,
@@ -141,6 +147,7 @@ impl std::str::FromStr for OpenAIClientProviderVariant {
141147 "openai" => Ok ( OpenAIClientProviderVariant :: Base ) ,
142148 "ollama" => Ok ( OpenAIClientProviderVariant :: Ollama ) ,
143149 "azure-openai" => Ok ( OpenAIClientProviderVariant :: Azure ) ,
150+ "openai-responses" => Ok ( OpenAIClientProviderVariant :: Responses ) ,
144151 "openai-generic" => Ok ( OpenAIClientProviderVariant :: Generic ) ,
145152 _ => Err ( anyhow:: anyhow!(
146153 "Invalid OpenAI client provider variant: {}" ,
@@ -171,6 +178,7 @@ impl ClientProvider {
171178 "openai" ,
172179 "openai-generic" ,
173180 "azure-openai" ,
181+ "openai-responses" ,
174182 "anthropic" ,
175183 "ollama" ,
176184 "round-robin" ,
@@ -191,7 +199,7 @@ impl std::fmt::Display for ClientSpec {
191199 }
192200}
193201
194- #[ derive( Clone , Debug , Hash ) ]
202+ #[ derive( Clone , Debug , Hash , Default ) ]
195203pub struct SupportedRequestModes {
196204 // If unset, treat as auto
197205 pub stream : Option < bool > ,
@@ -325,7 +333,7 @@ impl UnresolvedRolesSelection {
325333 }
326334}
327335
328- #[ derive( Clone , Debug ) ]
336+ #[ derive( Clone , Debug , Default ) ]
329337pub struct RolesSelection {
330338 allowed : Option < Vec < String > > ,
331339 default : Option < String > ,
@@ -409,6 +417,7 @@ impl AllowedRoleMetadata {
409417#[ derive( Clone , Debug , Hash ) ]
410418pub enum UnresolvedResponseType {
411419 OpenAI ,
420+ OpenAIResponses ,
412421 Anthropic ,
413422 Google ,
414423 Vertex ,
@@ -417,6 +426,7 @@ pub enum UnresolvedResponseType {
417426#[ derive( Clone , Debug , Hash ) ]
418427pub enum ResponseType {
419428 OpenAI ,
429+ OpenAIResponses ,
420430 Anthropic ,
421431 Google ,
422432 Vertex ,
@@ -430,9 +440,116 @@ impl UnresolvedResponseType {
430440 pub fn resolve ( & self , _: & impl GetEnvVar ) -> Result < ResponseType > {
431441 match self {
432442 Self :: OpenAI => Ok ( ResponseType :: OpenAI ) ,
443+ Self :: OpenAIResponses => Ok ( ResponseType :: OpenAIResponses ) ,
433444 Self :: Anthropic => Ok ( ResponseType :: Anthropic ) ,
434445 Self :: Google => Ok ( ResponseType :: Google ) ,
435446 Self :: Vertex => Ok ( ResponseType :: Vertex ) ,
436447 }
437448 }
438449}
450+
451+ #[ cfg( test) ]
452+ mod tests {
453+ use std:: str:: FromStr ;
454+
455+ use super :: * ;
456+
457+ #[ test]
458+ fn test_client_provider_parsing ( ) {
459+ // Test parsing of openai-responses provider
460+ let provider = ClientProvider :: from_str ( "openai-responses" ) ;
461+ assert ! ( provider. is_ok( ) ) ;
462+
463+ let provider = provider. unwrap ( ) ;
464+ match provider {
465+ ClientProvider :: OpenAI ( OpenAIClientProviderVariant :: Responses ) => {
466+ // Success!
467+ }
468+ _ => panic ! ( "Expected OpenAI Responses variant, got {:?}" , provider) ,
469+ }
470+ }
471+
472+ #[ test]
473+ fn test_openai_client_provider_variant_parsing ( ) {
474+ let variant = OpenAIClientProviderVariant :: from_str ( "openai-responses" ) ;
475+ assert ! ( variant. is_ok( ) ) ;
476+ assert_eq ! ( variant. unwrap( ) , OpenAIClientProviderVariant :: Responses ) ;
477+ }
478+
479+ #[ test]
480+ fn test_openai_responses_display ( ) {
481+ let variant = OpenAIClientProviderVariant :: Responses ;
482+ assert_eq ! ( variant. to_string( ) , "openai-responses" ) ;
483+ }
484+
485+ #[ test]
486+ fn test_openai_responses_in_allowed_providers ( ) {
487+ let allowed = ClientProvider :: allowed_providers ( ) ;
488+ assert ! ( allowed. contains( & "openai-responses" ) ) ;
489+ }
490+
491+ #[ test]
492+ fn test_response_type_parsing ( ) {
493+ // Test UnresolvedResponseType
494+ let unresolved = match "openai-responses" {
495+ "openai" => UnresolvedResponseType :: OpenAI ,
496+ "openai-responses" => UnresolvedResponseType :: OpenAIResponses ,
497+ "anthropic" => UnresolvedResponseType :: Anthropic ,
498+ "google" => UnresolvedResponseType :: Google ,
499+ "vertex" => UnresolvedResponseType :: Vertex ,
500+ _ => panic ! ( "Unknown response type" ) ,
501+ } ;
502+
503+ assert ! ( matches!(
504+ unresolved,
505+ UnresolvedResponseType :: OpenAIResponses
506+ ) ) ;
507+ }
508+
509+ #[ test]
510+ fn test_response_type_resolution ( ) {
511+ use baml_types:: GetEnvVar ;
512+
513+ struct MockEnvContext ;
514+ impl GetEnvVar for MockEnvContext {
515+ fn get_env_var ( & self , _name : & str ) -> Result < String , anyhow:: Error > {
516+ Err ( anyhow:: anyhow!( "No env var" ) )
517+ }
518+
519+ fn set_allow_missing_env_var ( & self , _: bool ) -> Self {
520+ MockEnvContext
521+ }
522+ }
523+
524+ let unresolved = UnresolvedResponseType :: OpenAIResponses ;
525+ let ctx = MockEnvContext ;
526+ let resolved = unresolved. resolve ( & ctx) ;
527+
528+ assert ! ( resolved. is_ok( ) ) ;
529+ assert ! ( matches!( resolved. unwrap( ) , ResponseType :: OpenAIResponses ) ) ;
530+ }
531+
532+ #[ test]
533+ fn test_provider_roundtrip ( ) {
534+ // Test that we can convert to string and back
535+ let original = ClientProvider :: OpenAI ( OpenAIClientProviderVariant :: Responses ) ;
536+ let string_repr = match & original {
537+ ClientProvider :: OpenAI ( variant) => variant. to_string ( ) ,
538+ _ => panic ! ( "Expected OpenAI provider" ) ,
539+ } ;
540+
541+ assert_eq ! ( string_repr, "openai-responses" ) ;
542+
543+ let parsed_back = ClientProvider :: from_str ( & string_repr) . unwrap ( ) ;
544+ assert_eq ! ( original, parsed_back) ;
545+ }
546+
547+ #[ test]
548+ fn test_invalid_provider_parsing ( ) {
549+ let result = ClientProvider :: from_str ( "invalid-provider" ) ;
550+ assert ! ( result. is_err( ) ) ;
551+
552+ let result = OpenAIClientProviderVariant :: from_str ( "invalid-variant" ) ;
553+ assert ! ( result. is_err( ) ) ;
554+ }
555+ }
0 commit comments