@@ -1116,6 +1116,217 @@ async IAsyncEnumerable<ChatResponseUpdate> YieldInnerClientUpdates(
11161116 }
11171117 }
11181118
1119+ [ Theory ]
1120+ [ InlineData ( false ) ]
1121+ [ InlineData ( true ) ]
1122+ public async Task FunctionCallReplacedWithApproval_MixedWithMcpApprovalAsync ( bool useAdditionalTools )
1123+ {
1124+ AITool [ ] tools =
1125+ [
1126+ new ApprovalRequiredAIFunction ( AIFunctionFactory . Create ( ( ) => "Result 1" , "Func" ) ) ,
1127+ new HostedMcpServerTool ( "myServer" , "https://localhost/mcp" )
1128+ ] ;
1129+
1130+ var options = new ChatOptions
1131+ {
1132+ Tools = useAdditionalTools ? null : tools
1133+ } ;
1134+
1135+ List < ChatMessage > input =
1136+ [
1137+ new ChatMessage ( ChatRole . User , "hello" ) ,
1138+ ] ;
1139+
1140+ List < ChatMessage > downstreamClientOutput =
1141+ [
1142+ new ChatMessage ( ChatRole . Assistant ,
1143+ [
1144+ new FunctionCallContent ( "callId1" , "Func" ) ,
1145+ new FunctionApprovalRequestContent ( "callId2" , new McpServerToolCallContent ( "callId2" , "McpCall" , "myServer" ) )
1146+ ] )
1147+ ] ;
1148+
1149+ List < ChatMessage > expectedOutput =
1150+ [
1151+ new ChatMessage ( ChatRole . Assistant ,
1152+ [
1153+ new FunctionApprovalRequestContent ( "callId1" , new FunctionCallContent ( "callId1" , "Func" ) ) ,
1154+ new FunctionApprovalRequestContent ( "callId2" , new McpServerToolCallContent ( "callId2" , "McpCall" , "myServer" ) )
1155+ ] )
1156+ ] ;
1157+
1158+ await InvokeAndAssertAsync ( options , input , downstreamClientOutput , expectedOutput , additionalTools : useAdditionalTools ? tools : null ) ;
1159+ await InvokeAndAssertStreamingAsync ( options , input , downstreamClientOutput , expectedOutput , additionalTools : useAdditionalTools ? tools : null ) ;
1160+ }
1161+
1162+ [ Theory ]
1163+ [ InlineData ( false ) ]
1164+ [ InlineData ( true ) ]
1165+ public async Task ApprovedApprovalResponseIsExecuted_MixedWithMcpApprovalAsync ( bool useAdditionalTools )
1166+ {
1167+ AITool [ ] tools =
1168+ [
1169+ new ApprovalRequiredAIFunction ( AIFunctionFactory . Create ( ( ) => "Result 1" , "Func" ) ) ,
1170+ new HostedMcpServerTool ( "myServer" , "https://localhost/mcp" )
1171+ ] ;
1172+
1173+ var options = new ChatOptions
1174+ {
1175+ Tools = useAdditionalTools ? null : tools
1176+ } ;
1177+
1178+ List < ChatMessage > input =
1179+ [
1180+ new ChatMessage ( ChatRole . User , "hello" ) ,
1181+ new ChatMessage ( ChatRole . Assistant ,
1182+ [
1183+ new FunctionApprovalRequestContent ( "callId1" , new FunctionCallContent ( "callId1" , "Func" ) ) ,
1184+ new FunctionApprovalRequestContent ( "callId2" , new McpServerToolCallContent ( "callId2" , "McpCall" , "myServer" ) )
1185+ ] ) { MessageId = "resp1" } ,
1186+ new ChatMessage ( ChatRole . User ,
1187+ [
1188+ new FunctionApprovalResponseContent ( "callId1" , true , new FunctionCallContent ( "callId1" , "Func" ) ) ,
1189+ new FunctionApprovalResponseContent ( "callId2" , true , new McpServerToolCallContent ( "callId2" , "McpCall" , "myServer" ) )
1190+ ] ) ,
1191+ ] ;
1192+
1193+ List < ChatMessage > expectedDownstreamClientInput =
1194+ [
1195+ new ChatMessage ( ChatRole . User , "hello" ) ,
1196+ new ChatMessage ( ChatRole . Assistant ,
1197+ [
1198+ new FunctionApprovalRequestContent ( "callId2" , new McpServerToolCallContent ( "callId2" , "McpCall" , "myServer" ) )
1199+ ] ) ,
1200+ new ChatMessage ( ChatRole . User ,
1201+ [
1202+ new FunctionApprovalResponseContent ( "callId2" , true , new McpServerToolCallContent ( "callId2" , "McpCall" , "myServer" ) )
1203+ ] ) ,
1204+ new ChatMessage ( ChatRole . Assistant ,
1205+ [
1206+ new FunctionCallContent ( "callId1" , "Func" )
1207+ ] ) ,
1208+ new ChatMessage ( ChatRole . Tool ,
1209+ [
1210+ new FunctionResultContent ( "callId1" , result : "Result 1" )
1211+ ] ) ,
1212+ ] ;
1213+
1214+ List < ChatMessage > downstreamClientOutput =
1215+ [
1216+ new ChatMessage ( ChatRole . Assistant , [
1217+ new McpServerToolResultContent ( "callId2" ) { Result = new List < AIContent > { new TextContent ( "Result 2" ) } } ,
1218+ new TextContent ( "world" )
1219+ ] )
1220+ ] ;
1221+
1222+ List < ChatMessage > output =
1223+ [
1224+ new ChatMessage ( ChatRole . Assistant ,
1225+ [
1226+ new FunctionCallContent ( "callId1" , "Func" )
1227+ ] ) ,
1228+ new ChatMessage ( ChatRole . Tool ,
1229+ [
1230+ new FunctionResultContent ( "callId1" , result : "Result 1" )
1231+ ] ) ,
1232+ new ChatMessage ( ChatRole . Assistant , [
1233+ new McpServerToolResultContent ( "callId2" ) { Result = new List < AIContent > { new TextContent ( "Result 2" ) } } ,
1234+ new TextContent ( "world" )
1235+ ] )
1236+ ] ;
1237+
1238+ await InvokeAndAssertAsync ( options , input , downstreamClientOutput , output , expectedDownstreamClientInput , additionalTools : useAdditionalTools ? tools : null ) ;
1239+ await InvokeAndAssertStreamingAsync ( options , input , downstreamClientOutput , output , expectedDownstreamClientInput , additionalTools : useAdditionalTools ? tools : null ) ;
1240+ }
1241+
1242+ [ Theory ]
1243+ [ InlineData ( false , false ) ]
1244+ [ InlineData ( false , true ) ]
1245+ [ InlineData ( true , false ) ]
1246+ [ InlineData ( true , true ) ]
1247+ public async Task RejectedApprovalResponses_MixedWithMcpApprovalAsync ( bool useAdditionalTools , bool approveMcp )
1248+ {
1249+ AITool [ ] tools =
1250+ [
1251+ new ApprovalRequiredAIFunction ( AIFunctionFactory . Create ( ( ) => "Result 1" , "Func" ) ) ,
1252+ new HostedMcpServerTool ( "myServer" , "https://localhost/mcp" )
1253+ ] ;
1254+
1255+ var options = new ChatOptions
1256+ {
1257+ Tools = useAdditionalTools ? null : tools
1258+ } ;
1259+
1260+ List < ChatMessage > input =
1261+ [
1262+ new ChatMessage ( ChatRole . User , "hello" ) ,
1263+ new ChatMessage ( ChatRole . Assistant ,
1264+ [
1265+ new FunctionApprovalRequestContent ( "callId1" , new FunctionCallContent ( "callId1" , "Func" ) ) ,
1266+ new FunctionApprovalRequestContent ( "callId2" , new McpServerToolCallContent ( "callId2" , "McpCall" , "myServer" ) )
1267+ ] ) { MessageId = "resp1" } ,
1268+ new ChatMessage ( ChatRole . User ,
1269+ [
1270+ new FunctionApprovalResponseContent ( "callId1" , ! approveMcp , new FunctionCallContent ( "callId1" , "Func" ) ) ,
1271+ new FunctionApprovalResponseContent ( "callId2" , approveMcp , new McpServerToolCallContent ( "callId2" , "McpCall" , "myServer" ) )
1272+ ] ) ,
1273+ ] ;
1274+
1275+ List < ChatMessage > expectedDownstreamClientInput = [
1276+ new ChatMessage ( ChatRole . User , "hello" ) ,
1277+ new ChatMessage ( ChatRole . Assistant ,
1278+ [
1279+ new FunctionApprovalRequestContent ( "callId2" , new McpServerToolCallContent ( "callId2" , "McpCall" , "myServer" ) )
1280+ ] ) ,
1281+ new ChatMessage ( ChatRole . User ,
1282+ [
1283+ new FunctionApprovalResponseContent ( "callId2" , approveMcp , new McpServerToolCallContent ( "callId2" , "McpCall" , "myServer" ) )
1284+ ] ) ,
1285+ new ChatMessage ( ChatRole . Assistant ,
1286+ [
1287+ new FunctionCallContent ( "callId1" , "Func" )
1288+ ] ) ,
1289+ new ChatMessage ( ChatRole . Tool ,
1290+ [
1291+ approveMcp ?
1292+ new FunctionResultContent ( "callId1" , result : "Tool call invocation rejected." ) :
1293+ new FunctionResultContent ( "callId1" , result : "Result 1" )
1294+ ] ) ,
1295+ ] ;
1296+
1297+ List < ChatMessage > downstreamClientOutput =
1298+ [
1299+ new ChatMessage ( ChatRole . Assistant , [
1300+ new TextContent ( "world" ) ,
1301+ .. approveMcp ?
1302+ [ new McpServerToolResultContent ( "callId2" ) { Result = new List < AIContent > { new TextContent ( "Result 2" ) } } ] :
1303+ Array . Empty < AIContent > ( )
1304+ ] )
1305+ ] ;
1306+
1307+ List < ChatMessage > output = [
1308+ new ChatMessage ( ChatRole . Assistant ,
1309+ [
1310+ new FunctionCallContent ( "callId1" , "Func" ) ,
1311+ ] ) ,
1312+ new ChatMessage ( ChatRole . Tool ,
1313+ [
1314+ approveMcp ?
1315+ new FunctionResultContent ( "callId1" , result : "Tool call invocation rejected." ) :
1316+ new FunctionResultContent ( "callId1" , result : "Result 1" )
1317+ ] ) ,
1318+ new ChatMessage ( ChatRole . Assistant , [
1319+ new TextContent ( "world" ) ,
1320+ .. approveMcp ?
1321+ [ new McpServerToolResultContent ( "callId2" ) { Result = new List < AIContent > { new TextContent ( "Result 2" ) } } ] :
1322+ Array . Empty < AIContent > ( )
1323+ ] )
1324+ ] ;
1325+
1326+ await InvokeAndAssertAsync ( options , input , downstreamClientOutput , output , expectedDownstreamClientInput , additionalTools : useAdditionalTools ? tools : null ) ;
1327+ await InvokeAndAssertStreamingAsync ( options , input , downstreamClientOutput , output , expectedDownstreamClientInput , additionalTools : useAdditionalTools ? tools : null ) ;
1328+ }
1329+
11191330 private static Task < List < ChatMessage > > InvokeAndAssertAsync (
11201331 ChatOptions ? options ,
11211332 List < ChatMessage > input ,
0 commit comments