@@ -637,7 +637,7 @@ private async Task HandleBroadcastEventAsync(SessionEvent sessionEvent)
637637 ? new ElicitationSchema
638638 {
639639 Type = data . RequestedSchema . Type ,
640- Properties = data . RequestedSchema . Properties ,
640+ Properties = data . RequestedSchema . Properties . ToDictionary ( kvp => kvp . Key , kvp => ( object ) kvp . Value ) ,
641641 Required = data . RequestedSchema . Required ? . ToList ( )
642642 }
643643 : null ;
@@ -687,7 +687,7 @@ await HandleElicitationRequestAsync(
687687 /// <summary>
688688 /// Executes a tool handler and sends the result back via the HandlePendingToolCall RPC.
689689 /// </summary>
690- private async Task ExecuteToolAndRespondAsync ( string requestId , string toolName , string toolCallId , object ? arguments , AIFunction tool )
690+ private async Task ExecuteToolAndRespondAsync ( string requestId , string toolName , string toolCallId , JsonElement ? arguments , AIFunction tool )
691691 {
692692 try
693693 {
@@ -707,13 +707,8 @@ private async Task ExecuteToolAndRespondAsync(string requestId, string toolName,
707707 }
708708 } ;
709709
710- if ( arguments is not null )
710+ if ( arguments is JsonElement incomingJsonArgs )
711711 {
712- if ( arguments is not JsonElement incomingJsonArgs )
713- {
714- throw new InvalidOperationException ( $ "Incoming arguments must be a { nameof ( JsonElement ) } ; received { arguments . GetType ( ) . Name } ") ;
715- }
716-
717712 foreach ( var prop in incomingJsonArgs . EnumerateObject ( ) )
718713 {
719714 aiFunctionArgs [ prop . Name ] = prop . Value ;
@@ -948,7 +943,9 @@ private async Task HandleElicitationRequestAsync(ElicitationContext context, str
948943 await Rpc . Ui . HandlePendingElicitationAsync ( requestId , new UIElicitationResponse
949944 {
950945 Action = result . Action ,
951- Content = result . Content
946+ Content = result . Content ? . ToDictionary (
947+ kvp => kvp . Key ,
948+ kvp => CopilotClient . ToJsonElementForWire ( kvp . Value ) ! . Value )
952949 } ) ;
953950 LoggingHelpers . LogTiming ( _logger , LogLevel . Debug , null ,
954951 "CopilotSession.HandleElicitationRequestAsync response sent successfully. Elapsed={Elapsed}, SessionId={SessionId}, RequestId={RequestId}" ,
@@ -991,6 +988,15 @@ private void AssertElicitation()
991988 /// </summary>
992989 private sealed class SessionUiApiImpl ( CopilotSession session ) : ISessionUiApi
993990 {
991+ // Parses a JSON string and returns a detached JsonElement. Using `using`
992+ // ensures the pooled buffers backing the JsonDocument are released
993+ // promptly; the cloned RootElement is independent of the document.
994+ private static JsonElement ParseJsonElement ( string json )
995+ {
996+ using var doc = JsonDocument . Parse ( json ) ;
997+ return doc . RootElement . Clone ( ) ;
998+ }
999+
9941000 public async Task < ElicitationResult > ElicitAsync ( ElicitationParams elicitationParams , CancellationToken cancellationToken )
9951001 {
9961002 ArgumentNullException . ThrowIfNull ( elicitationParams ) ;
@@ -1000,12 +1006,18 @@ public async Task<ElicitationResult> ElicitAsync(ElicitationParams elicitationPa
10001006 var schema = new UIElicitationSchema
10011007 {
10021008 Type = elicitationParams . RequestedSchema . Type ,
1003- Properties = elicitationParams . RequestedSchema . Properties ,
1009+ Properties = elicitationParams . RequestedSchema . Properties . ToDictionary (
1010+ kvp => kvp . Key ,
1011+ kvp => CopilotClient . ToJsonElementForWire ( kvp . Value ) ! . Value ) ,
10041012 Required = elicitationParams . RequestedSchema . Required
10051013 } ;
10061014
10071015 var result = await session . Rpc . Ui . ElicitationAsync ( elicitationParams . Message , schema , cancellationToken ) ;
1008- return new ElicitationResult { Action = result . Action , Content = result . Content } ;
1016+ return new ElicitationResult
1017+ {
1018+ Action = result . Action ,
1019+ Content = result . Content ? . ToDictionary ( kvp => kvp . Key , kvp => ( object ) kvp . Value )
1020+ } ;
10091021 }
10101022
10111023 public async Task < bool > ConfirmAsync ( string message , CancellationToken cancellationToken )
@@ -1017,9 +1029,9 @@ public async Task<bool> ConfirmAsync(string message, CancellationToken cancellat
10171029 var schema = new UIElicitationSchema
10181030 {
10191031 Type = "object" ,
1020- Properties = new Dictionary < string , object >
1032+ Properties = new Dictionary < string , JsonElement >
10211033 {
1022- [ "confirmed" ] = new Dictionary < string , object > { [ "type" ] = "boolean" , [ "default" ] = true }
1034+ [ "confirmed" ] = ParseJsonElement ( """{ "type": "boolean","default": true}""" )
10231035 } ,
10241036 Required = [ "confirmed" ]
10251037 } ;
@@ -1029,11 +1041,10 @@ public async Task<bool> ConfirmAsync(string message, CancellationToken cancellat
10291041 && result . Content != null
10301042 && result . Content . TryGetValue ( "confirmed" , out var val ) )
10311043 {
1032- return val switch
1044+ return val . ValueKind switch
10331045 {
1034- bool b => b ,
1035- JsonElement { ValueKind : JsonValueKind . True } => true ,
1036- JsonElement { ValueKind : JsonValueKind . False } => false ,
1046+ JsonValueKind . True => true ,
1047+ JsonValueKind . False => false ,
10371048 _ => false
10381049 } ;
10391050 }
@@ -1048,12 +1059,13 @@ public async Task<bool> ConfirmAsync(string message, CancellationToken cancellat
10481059 session . ThrowIfDisposed ( ) ;
10491060 session . AssertElicitation ( ) ;
10501061
1062+ var enumJson = JsonSerializer . Serialize ( options , TypesJsonContext . Default . StringArray ) ;
10511063 var schema = new UIElicitationSchema
10521064 {
10531065 Type = "object" ,
1054- Properties = new Dictionary < string , object >
1066+ Properties = new Dictionary < string , JsonElement >
10551067 {
1056- [ "selection" ] = new Dictionary < string , object > { [ "type" ] = "string" , [ "enum" ] = options }
1068+ [ "selection" ] = ParseJsonElement ( $$ """ { "type": "string","enum": {{ enumJson }} } """ )
10571069 } ,
10581070 Required = [ "selection" ]
10591071 } ;
@@ -1063,12 +1075,7 @@ public async Task<bool> ConfirmAsync(string message, CancellationToken cancellat
10631075 && result . Content != null
10641076 && result . Content . TryGetValue ( "selection" , out var val ) )
10651077 {
1066- return val switch
1067- {
1068- string s => s ,
1069- JsonElement { ValueKind : JsonValueKind . String } je => je . GetString ( ) ,
1070- _ => val . ToString ( )
1071- } ;
1078+ return val . ValueKind == JsonValueKind . String ? val . GetString ( ) : val . ToString ( ) ;
10721079 }
10731080
10741081 return null ;
@@ -1080,18 +1087,21 @@ public async Task<bool> ConfirmAsync(string message, CancellationToken cancellat
10801087 session . ThrowIfDisposed ( ) ;
10811088 session . AssertElicitation ( ) ;
10821089
1083- var field = new Dictionary < string , object > { [ "type" ] = "string" } ;
1084- if ( options ? . Title != null ) field [ "title" ] = options . Title ;
1085- if ( options ? . Description != null ) field [ "description" ] = options . Description ;
1086- if ( options ? . MinLength != null ) field [ "minLength" ] = options . MinLength ;
1087- if ( options ? . MaxLength != null ) field [ "maxLength" ] = options . MaxLength ;
1088- if ( options ? . Format != null ) field [ "format" ] = options . Format ;
1089- if ( options ? . Default != null ) field [ "default" ] = options . Default ;
1090+ var fieldNode = new System . Text . Json . Nodes . JsonObject { [ "type" ] = "string" } ;
1091+ if ( options ? . Title != null ) fieldNode [ "title" ] = options . Title ;
1092+ if ( options ? . Description != null ) fieldNode [ "description" ] = options . Description ;
1093+ if ( options ? . MinLength != null ) fieldNode [ "minLength" ] = options . MinLength ;
1094+ if ( options ? . MaxLength != null ) fieldNode [ "maxLength" ] = options . MaxLength ;
1095+ if ( options ? . Format != null ) fieldNode [ "format" ] = options . Format ;
1096+ if ( options ? . Default != null ) fieldNode [ "default" ] = options . Default ;
10901097
10911098 var schema = new UIElicitationSchema
10921099 {
10931100 Type = "object" ,
1094- Properties = new Dictionary < string , object > { [ "value" ] = field } ,
1101+ Properties = new Dictionary < string , JsonElement >
1102+ {
1103+ [ "value" ] = ParseJsonElement ( fieldNode . ToJsonString ( ) )
1104+ } ,
10951105 Required = [ "value" ]
10961106 } ;
10971107
@@ -1100,12 +1110,7 @@ public async Task<bool> ConfirmAsync(string message, CancellationToken cancellat
11001110 && result . Content != null
11011111 && result . Content . TryGetValue ( "value" , out var val ) )
11021112 {
1103- return val switch
1104- {
1105- string s => s ,
1106- JsonElement { ValueKind : JsonValueKind . String } je => je . GetString ( ) ,
1107- _ => val . ToString ( )
1108- } ;
1113+ return val . ValueKind == JsonValueKind . String ? val . GetString ( ) : val . ToString ( ) ;
11091114 }
11101115
11111116 return null ;
0 commit comments