@@ -67,6 +67,74 @@ public void SerializerOptions_CanResolveRequestIdTypeInfo()
6767 Assert . Equal ( typeof ( RequestId ) , typeInfo . Type ) ;
6868 }
6969
70+ [ Fact ]
71+ public void ProviderConfig_CanSerializeHeaders_WithSdkOptions ( )
72+ {
73+ var options = GetSerializerOptions ( ) ;
74+ var original = new ProviderConfig
75+ {
76+ BaseUrl = "https://example.com/provider" ,
77+ Headers = new Dictionary < string , string > { [ "Authorization" ] = "Bearer provider-token" }
78+ } ;
79+
80+ var json = JsonSerializer . Serialize ( original , options ) ;
81+ using var document = JsonDocument . Parse ( json ) ;
82+ var root = document . RootElement ;
83+ Assert . Equal ( "https://example.com/provider" , root . GetProperty ( "baseUrl" ) . GetString ( ) ) ;
84+ Assert . Equal ( "Bearer provider-token" , root . GetProperty ( "headers" ) . GetProperty ( "Authorization" ) . GetString ( ) ) ;
85+
86+ var deserialized = JsonSerializer . Deserialize < ProviderConfig > ( json , options ) ;
87+ Assert . NotNull ( deserialized ) ;
88+ Assert . Equal ( "https://example.com/provider" , deserialized . BaseUrl ) ;
89+ Assert . Equal ( "Bearer provider-token" , deserialized . Headers ! [ "Authorization" ] ) ;
90+ }
91+
92+ [ Fact ]
93+ public void MessageOptions_CanSerializeRequestHeaders_WithSdkOptions ( )
94+ {
95+ var options = GetSerializerOptions ( ) ;
96+ var original = new MessageOptions
97+ {
98+ Prompt = "real prompt" ,
99+ Mode = "plan" ,
100+ RequestHeaders = new Dictionary < string , string > { [ "X-Trace" ] = "trace-value" }
101+ } ;
102+
103+ var json = JsonSerializer . Serialize ( original , options ) ;
104+ using var document = JsonDocument . Parse ( json ) ;
105+ var root = document . RootElement ;
106+ Assert . Equal ( "real prompt" , root . GetProperty ( "prompt" ) . GetString ( ) ) ;
107+ Assert . Equal ( "plan" , root . GetProperty ( "mode" ) . GetString ( ) ) ;
108+ Assert . Equal ( "trace-value" , root . GetProperty ( "requestHeaders" ) . GetProperty ( "X-Trace" ) . GetString ( ) ) ;
109+
110+ var deserialized = JsonSerializer . Deserialize < MessageOptions > ( json , options ) ;
111+ Assert . NotNull ( deserialized ) ;
112+ Assert . Equal ( "real prompt" , deserialized . Prompt ) ;
113+ Assert . Equal ( "plan" , deserialized . Mode ) ;
114+ Assert . Equal ( "trace-value" , deserialized . RequestHeaders ! [ "X-Trace" ] ) ;
115+ }
116+
117+ [ Fact ]
118+ public void SendMessageRequest_CanSerializeRequestHeaders_WithSdkOptions ( )
119+ {
120+ var options = GetSerializerOptions ( ) ;
121+ var requestType = GetNestedType ( typeof ( CopilotSession ) , "SendMessageRequest" ) ;
122+ var request = CreateInternalRequest (
123+ requestType ,
124+ ( "SessionId" , "session-id" ) ,
125+ ( "Prompt" , "real prompt" ) ,
126+ ( "Mode" , "plan" ) ,
127+ ( "RequestHeaders" , new Dictionary < string , string > { [ "X-Trace" ] = "trace-value" } ) ) ;
128+
129+ var json = JsonSerializer . Serialize ( request , requestType , options ) ;
130+ using var document = JsonDocument . Parse ( json ) ;
131+ var root = document . RootElement ;
132+ Assert . Equal ( "session-id" , root . GetProperty ( "sessionId" ) . GetString ( ) ) ;
133+ Assert . Equal ( "real prompt" , root . GetProperty ( "prompt" ) . GetString ( ) ) ;
134+ Assert . Equal ( "plan" , root . GetProperty ( "mode" ) . GetString ( ) ) ;
135+ Assert . Equal ( "trace-value" , root . GetProperty ( "requestHeaders" ) . GetProperty ( "X-Trace" ) . GetString ( ) ) ;
136+ }
137+
70138 private static JsonSerializerOptions GetSerializerOptions ( )
71139 {
72140 var prop = typeof ( CopilotClient )
@@ -77,4 +145,34 @@ private static JsonSerializerOptions GetSerializerOptions()
77145 Assert . NotNull ( options ) ;
78146 return options ;
79147 }
148+
149+ private static Type GetNestedType ( Type containingType , string name )
150+ {
151+ var type = containingType . GetNestedType ( name , System . Reflection . BindingFlags . NonPublic ) ;
152+ Assert . NotNull ( type ) ;
153+ return type ! ;
154+ }
155+
156+ private static object CreateInternalRequest ( Type type , params ( string Name , object ? Value ) [ ] properties )
157+ {
158+ var instance = System . Runtime . CompilerServices . RuntimeHelpers . GetUninitializedObject ( type ) ;
159+
160+ foreach ( var ( name , value ) in properties )
161+ {
162+ var property = type . GetProperty ( name , System . Reflection . BindingFlags . Instance | System . Reflection . BindingFlags . Public | System . Reflection . BindingFlags . NonPublic ) ;
163+ Assert . NotNull ( property ) ;
164+
165+ if ( property ! . SetMethod is not null )
166+ {
167+ property . SetValue ( instance , value ) ;
168+ continue ;
169+ }
170+
171+ var field = type . GetField ( $ "<{ name } >k__BackingField", System . Reflection . BindingFlags . Instance | System . Reflection . BindingFlags . NonPublic ) ;
172+ Assert . NotNull ( field ) ;
173+ field ! . SetValue ( instance , value ) ;
174+ }
175+
176+ return instance ;
177+ }
80178}
0 commit comments