@@ -5809,4 +5809,281 @@ mod test_serialization {
58095809 _ => panic ! ( "Expected Select kind" ) ,
58105810 }
58115811 }
5812+
5813+ #[ cfg( feature = "unstable_llm_providers" ) ]
5814+ #[ test]
5815+ fn test_llm_protocol_known_variants ( ) {
5816+ assert_eq ! (
5817+ serde_json:: to_value( & LlmProtocol :: Anthropic ) . unwrap( ) ,
5818+ json!( "anthropic" )
5819+ ) ;
5820+ assert_eq ! (
5821+ serde_json:: to_value( & LlmProtocol :: OpenAi ) . unwrap( ) ,
5822+ json!( "openai" )
5823+ ) ;
5824+ assert_eq ! (
5825+ serde_json:: to_value( & LlmProtocol :: Azure ) . unwrap( ) ,
5826+ json!( "azure" )
5827+ ) ;
5828+ assert_eq ! (
5829+ serde_json:: to_value( & LlmProtocol :: Vertex ) . unwrap( ) ,
5830+ json!( "vertex" )
5831+ ) ;
5832+ assert_eq ! (
5833+ serde_json:: to_value( & LlmProtocol :: Bedrock ) . unwrap( ) ,
5834+ json!( "bedrock" )
5835+ ) ;
5836+
5837+ assert_eq ! (
5838+ serde_json:: from_str:: <LlmProtocol >( "\" anthropic\" " ) . unwrap( ) ,
5839+ LlmProtocol :: Anthropic
5840+ ) ;
5841+ assert_eq ! (
5842+ serde_json:: from_str:: <LlmProtocol >( "\" openai\" " ) . unwrap( ) ,
5843+ LlmProtocol :: OpenAi
5844+ ) ;
5845+ assert_eq ! (
5846+ serde_json:: from_str:: <LlmProtocol >( "\" azure\" " ) . unwrap( ) ,
5847+ LlmProtocol :: Azure
5848+ ) ;
5849+ assert_eq ! (
5850+ serde_json:: from_str:: <LlmProtocol >( "\" vertex\" " ) . unwrap( ) ,
5851+ LlmProtocol :: Vertex
5852+ ) ;
5853+ assert_eq ! (
5854+ serde_json:: from_str:: <LlmProtocol >( "\" bedrock\" " ) . unwrap( ) ,
5855+ LlmProtocol :: Bedrock
5856+ ) ;
5857+ }
5858+
5859+ #[ cfg( feature = "unstable_llm_providers" ) ]
5860+ #[ test]
5861+ fn test_llm_protocol_unknown_variant ( ) {
5862+ let unknown: LlmProtocol = serde_json:: from_str ( "\" cohere\" " ) . unwrap ( ) ;
5863+ assert_eq ! ( unknown, LlmProtocol :: Other ( "cohere" . to_string( ) ) ) ;
5864+
5865+ let json = serde_json:: to_value ( & unknown) . unwrap ( ) ;
5866+ assert_eq ! ( json, json!( "cohere" ) ) ;
5867+ }
5868+
5869+ #[ cfg( feature = "unstable_llm_providers" ) ]
5870+ #[ test]
5871+ fn test_provider_current_config_serialization ( ) {
5872+ let config =
5873+ ProviderCurrentConfig :: new ( LlmProtocol :: Anthropic , "https://api.anthropic.com" ) ;
5874+
5875+ let json = serde_json:: to_value ( & config) . unwrap ( ) ;
5876+ assert_eq ! (
5877+ json,
5878+ json!( {
5879+ "apiType" : "anthropic" ,
5880+ "baseUrl" : "https://api.anthropic.com"
5881+ } )
5882+ ) ;
5883+
5884+ let deserialized: ProviderCurrentConfig = serde_json:: from_value ( json) . unwrap ( ) ;
5885+ assert_eq ! ( deserialized. api_type, LlmProtocol :: Anthropic ) ;
5886+ assert_eq ! ( deserialized. base_url, "https://api.anthropic.com" ) ;
5887+ }
5888+
5889+ #[ cfg( feature = "unstable_llm_providers" ) ]
5890+ #[ test]
5891+ fn test_provider_info_with_current_config ( ) {
5892+ let info = ProviderInfo :: new (
5893+ "main" ,
5894+ vec ! [ LlmProtocol :: Anthropic , LlmProtocol :: OpenAi ] ,
5895+ true ,
5896+ Some ( ProviderCurrentConfig :: new (
5897+ LlmProtocol :: Anthropic ,
5898+ "https://api.anthropic.com" ,
5899+ ) ) ,
5900+ ) ;
5901+
5902+ let json = serde_json:: to_value ( & info) . unwrap ( ) ;
5903+ assert_eq ! (
5904+ json,
5905+ json!( {
5906+ "id" : "main" ,
5907+ "supported" : [ "anthropic" , "openai" ] ,
5908+ "required" : true ,
5909+ "current" : {
5910+ "apiType" : "anthropic" ,
5911+ "baseUrl" : "https://api.anthropic.com"
5912+ }
5913+ } )
5914+ ) ;
5915+
5916+ let deserialized: ProviderInfo = serde_json:: from_value ( json) . unwrap ( ) ;
5917+ assert_eq ! ( deserialized. id, "main" ) ;
5918+ assert_eq ! ( deserialized. supported. len( ) , 2 ) ;
5919+ assert ! ( deserialized. required) ;
5920+ assert ! ( deserialized. current. is_value( ) ) ;
5921+ assert_eq ! (
5922+ deserialized. current. value( ) . unwrap( ) . api_type,
5923+ LlmProtocol :: Anthropic
5924+ ) ;
5925+ }
5926+
5927+ #[ cfg( feature = "unstable_llm_providers" ) ]
5928+ #[ test]
5929+ fn test_provider_info_disabled ( ) {
5930+ let info = ProviderInfo :: new (
5931+ "secondary" ,
5932+ vec ! [ LlmProtocol :: OpenAi ] ,
5933+ false ,
5934+ Nullable :: < ProviderCurrentConfig > :: null ( ) ,
5935+ ) ;
5936+
5937+ let json = serde_json:: to_value ( & info) . unwrap ( ) ;
5938+ assert_eq ! (
5939+ json,
5940+ json!( {
5941+ "id" : "secondary" ,
5942+ "supported" : [ "openai" ] ,
5943+ "required" : false ,
5944+ "current" : null
5945+ } )
5946+ ) ;
5947+
5948+ let deserialized: ProviderInfo = serde_json:: from_value ( json) . unwrap ( ) ;
5949+ assert_eq ! ( deserialized. id, "secondary" ) ;
5950+ assert ! ( !deserialized. required) ;
5951+ assert ! ( deserialized. current. is_null( ) ) ;
5952+ }
5953+
5954+ #[ cfg( feature = "unstable_llm_providers" ) ]
5955+ #[ test]
5956+ fn test_provider_info_missing_current_fails ( ) {
5957+ // current is required-but-nullable — omitting it entirely must fail
5958+ let json = json ! ( {
5959+ "id" : "main" ,
5960+ "supported" : [ "anthropic" ] ,
5961+ "required" : true
5962+ } ) ;
5963+ assert ! ( serde_json:: from_value:: <ProviderInfo >( json) . is_err( ) ) ;
5964+ }
5965+
5966+ #[ cfg( feature = "unstable_llm_providers" ) ]
5967+ #[ test]
5968+ fn test_list_providers_response_serialization ( ) {
5969+ let response = ListProvidersResponse :: new ( vec ! [ ProviderInfo :: new(
5970+ "main" ,
5971+ vec![ LlmProtocol :: Anthropic ] ,
5972+ true ,
5973+ Some ( ProviderCurrentConfig :: new(
5974+ LlmProtocol :: Anthropic ,
5975+ "https://api.anthropic.com" ,
5976+ ) ) ,
5977+ ) ] ) ;
5978+
5979+ let json = serde_json:: to_value ( & response) . unwrap ( ) ;
5980+ assert_eq ! ( json[ "providers" ] . as_array( ) . unwrap( ) . len( ) , 1 ) ;
5981+ assert_eq ! ( json[ "providers" ] [ 0 ] [ "id" ] , "main" ) ;
5982+
5983+ let deserialized: ListProvidersResponse = serde_json:: from_value ( json) . unwrap ( ) ;
5984+ assert_eq ! ( deserialized. providers. len( ) , 1 ) ;
5985+ }
5986+
5987+ #[ cfg( feature = "unstable_llm_providers" ) ]
5988+ #[ test]
5989+ fn test_set_providers_request_serialization ( ) {
5990+ use std:: collections:: HashMap ;
5991+
5992+ let mut headers = HashMap :: new ( ) ;
5993+ headers. insert ( "Authorization" . to_string ( ) , "Bearer sk-test" . to_string ( ) ) ;
5994+
5995+ let request =
5996+ SetProvidersRequest :: new ( "main" , LlmProtocol :: OpenAi , "https://api.openai.com/v1" )
5997+ . headers ( headers) ;
5998+
5999+ let json = serde_json:: to_value ( & request) . unwrap ( ) ;
6000+ assert_eq ! (
6001+ json,
6002+ json!( {
6003+ "id" : "main" ,
6004+ "apiType" : "openai" ,
6005+ "baseUrl" : "https://api.openai.com/v1" ,
6006+ "headers" : {
6007+ "Authorization" : "Bearer sk-test"
6008+ }
6009+ } )
6010+ ) ;
6011+
6012+ let deserialized: SetProvidersRequest = serde_json:: from_value ( json) . unwrap ( ) ;
6013+ assert_eq ! ( deserialized. id, "main" ) ;
6014+ assert_eq ! ( deserialized. api_type, LlmProtocol :: OpenAi ) ;
6015+ assert_eq ! ( deserialized. base_url, "https://api.openai.com/v1" ) ;
6016+ assert_eq ! ( deserialized. headers. len( ) , 1 ) ;
6017+ assert_eq ! (
6018+ deserialized. headers. get( "Authorization" ) . unwrap( ) ,
6019+ "Bearer sk-test"
6020+ ) ;
6021+ }
6022+
6023+ #[ cfg( feature = "unstable_llm_providers" ) ]
6024+ #[ test]
6025+ fn test_set_providers_request_omits_empty_headers ( ) {
6026+ let request =
6027+ SetProvidersRequest :: new ( "main" , LlmProtocol :: Anthropic , "https://api.anthropic.com" ) ;
6028+
6029+ let json = serde_json:: to_value ( & request) . unwrap ( ) ;
6030+ // headers should be omitted when empty
6031+ assert ! ( !json. as_object( ) . unwrap( ) . contains_key( "headers" ) ) ;
6032+ }
6033+
6034+ #[ cfg( feature = "unstable_llm_providers" ) ]
6035+ #[ test]
6036+ fn test_set_providers_request_debug_redacts_headers ( ) {
6037+ use std:: collections:: HashMap ;
6038+
6039+ let mut headers = HashMap :: new ( ) ;
6040+ headers. insert (
6041+ "Authorization" . to_string ( ) ,
6042+ "Bearer sk-secret-key" . to_string ( ) ,
6043+ ) ;
6044+
6045+ let request =
6046+ SetProvidersRequest :: new ( "main" , LlmProtocol :: Anthropic , "https://api.anthropic.com" )
6047+ . headers ( headers) ;
6048+
6049+ let debug = format ! ( "{:?}" , request) ;
6050+ assert ! ( debug. contains( "[REDACTED]" ) ) ;
6051+ assert ! ( !debug. contains( "sk-secret-key" ) ) ;
6052+ }
6053+
6054+ #[ cfg( feature = "unstable_llm_providers" ) ]
6055+ #[ test]
6056+ fn test_disable_providers_request_serialization ( ) {
6057+ let request = DisableProvidersRequest :: new ( "secondary" ) ;
6058+
6059+ let json = serde_json:: to_value ( & request) . unwrap ( ) ;
6060+ assert_eq ! ( json, json!( { "id" : "secondary" } ) ) ;
6061+
6062+ let deserialized: DisableProvidersRequest = serde_json:: from_value ( json) . unwrap ( ) ;
6063+ assert_eq ! ( deserialized. id, "secondary" ) ;
6064+ }
6065+
6066+ #[ cfg( feature = "unstable_llm_providers" ) ]
6067+ #[ test]
6068+ fn test_providers_capabilities_serialization ( ) {
6069+ let caps = ProvidersCapabilities :: new ( ) ;
6070+
6071+ let json = serde_json:: to_value ( & caps) . unwrap ( ) ;
6072+ assert_eq ! ( json, json!( { } ) ) ;
6073+
6074+ let deserialized: ProvidersCapabilities = serde_json:: from_value ( json) . unwrap ( ) ;
6075+ assert ! ( deserialized. meta. is_none( ) ) ;
6076+ }
6077+
6078+ #[ cfg( feature = "unstable_llm_providers" ) ]
6079+ #[ test]
6080+ fn test_agent_capabilities_with_providers ( ) {
6081+ let caps = AgentCapabilities :: new ( ) . providers ( ProvidersCapabilities :: new ( ) ) ;
6082+
6083+ let json = serde_json:: to_value ( & caps) . unwrap ( ) ;
6084+ assert_eq ! ( json[ "providers" ] , json!( { } ) ) ;
6085+
6086+ let deserialized: AgentCapabilities = serde_json:: from_value ( json) . unwrap ( ) ;
6087+ assert ! ( deserialized. providers. is_some( ) ) ;
6088+ }
58126089}
0 commit comments