@@ -8,6 +8,10 @@ namespace tryAGI.OpenAI.IntegrationTests;
88/// </summary>
99public partial class Tests
1010{
11+ // ═══════════════════════════════════════════════════════════════
12+ // Shared helpers
13+ // ═══════════════════════════════════════════════════════════════
14+
1115 private async Task ChatClient_CustomProvider_GetResponseAsync ( CustomProvider provider )
1216 {
1317 var ( api , model ) = GetAuthorizedChatApi ( provider ) ;
@@ -43,7 +47,89 @@ [new Meai.ChatMessage(Meai.ChatRole.User, "Count from 1 to 5.")],
4347 Console . WriteLine ( $ "[{ provider } ] Got { updates . Count } streaming updates") ;
4448 }
4549
46- // --- DeepInfra ---
50+ private async Task ChatClient_CustomProvider_ToolCallingAsync ( CustomProvider provider )
51+ {
52+ var ( api , model ) = GetAuthorizedChatApi ( provider ) ;
53+ using var _ = api ;
54+ Meai . IChatClient chatClient = api ;
55+
56+ var tool = Meai . AIFunctionFactory . Create (
57+ ( string city ) => city switch
58+ {
59+ "Paris" => "22°C, sunny" ,
60+ "London" => "15°C, cloudy" ,
61+ _ => "Unknown" ,
62+ } ,
63+ name : "GetWeather" ,
64+ description : "Gets the current weather for a city" ) ;
65+
66+ var response = await chatClient . GetResponseAsync (
67+ [ new Meai . ChatMessage ( Meai . ChatRole . User , "What's the weather in Paris?" ) ] ,
68+ new Meai . ChatOptions
69+ {
70+ ModelId = model ,
71+ Tools = [ tool ] ,
72+ } ) ;
73+
74+ response . Should ( ) . NotBeNull ( ) ;
75+ response . FinishReason . Should ( ) . Be ( Meai . ChatFinishReason . ToolCalls ) ;
76+
77+ var functionCall = response . Messages
78+ . SelectMany ( m => m . Contents )
79+ . OfType < Meai . FunctionCallContent > ( )
80+ . FirstOrDefault ( ) ;
81+
82+ functionCall . Should ( ) . NotBeNull ( ) ;
83+ functionCall ! . Name . Should ( ) . Be ( "GetWeather" ) ;
84+ Console . WriteLine ( $ "[{ provider } ] Tool call: { functionCall . Name } ({ string . Join ( ", " , functionCall . Arguments ? . Select ( kv => $ "{ kv . Key } ={ kv . Value } ") ?? [ ] ) } )") ;
85+ }
86+
87+ // ═══════════════════════════════════════════════════════════════
88+ // Azure
89+ // ═══════════════════════════════════════════════════════════════
90+
91+ [ TestMethod ]
92+ public async Task ChatClient_Azure_GetResponse ( )
93+ {
94+ var ( api , model ) = GetAuthorizedChatApi ( CustomProvider . Azure ) ;
95+ using var _ = api ;
96+ Meai . IChatClient chatClient = api ;
97+
98+ var response = await chatClient . GetResponseAsync (
99+ [ new Meai . ChatMessage ( Meai . ChatRole . User , "Say hello in exactly 3 words." ) ] ,
100+ new Meai . ChatOptions { ModelId = model } ) ;
101+
102+ response . Should ( ) . NotBeNull ( ) ;
103+ response . Messages . Should ( ) . NotBeEmpty ( ) ;
104+ Console . WriteLine ( $ "[Azure] { response . Messages [ 0 ] . Text } ") ;
105+ }
106+
107+ [ TestMethod ]
108+ public async Task ChatClient_Azure_Streaming ( )
109+ {
110+ var ( api , model ) = GetAuthorizedChatApi ( CustomProvider . Azure ) ;
111+ using var _ = api ;
112+ Meai . IChatClient chatClient = api ;
113+
114+ var updates = new List < Meai . ChatResponseUpdate > ( ) ;
115+ await foreach ( var update in chatClient . GetStreamingResponseAsync (
116+ [ new Meai . ChatMessage ( Meai . ChatRole . User , "Count from 1 to 5." ) ] ,
117+ new Meai . ChatOptions { ModelId = model } ) )
118+ {
119+ updates . Add ( update ) ;
120+ }
121+
122+ updates . Should ( ) . NotBeEmpty ( ) ;
123+ Console . WriteLine ( $ "[Azure] Got { updates . Count } streaming updates") ;
124+ }
125+
126+ [ TestMethod ]
127+ public Task ChatClient_Azure_ToolCalling ( ) =>
128+ ChatClient_CustomProvider_ToolCallingAsync ( CustomProvider . Azure ) ;
129+
130+ // ═══════════════════════════════════════════════════════════════
131+ // DeepInfra
132+ // ═══════════════════════════════════════════════════════════════
47133
48134 [ TestMethod ]
49135 public Task ChatClient_DeepInfra_GetResponse ( ) =>
@@ -53,6 +139,10 @@ public Task ChatClient_DeepInfra_GetResponse() =>
53139 public Task ChatClient_DeepInfra_Streaming ( ) =>
54140 ChatClient_CustomProvider_StreamingAsync ( CustomProvider . DeepInfra ) ;
55141
142+ [ TestMethod ]
143+ public Task ChatClient_DeepInfra_ToolCalling ( ) =>
144+ ChatClient_CustomProvider_ToolCallingAsync ( CustomProvider . DeepInfra ) ;
145+
56146 // --- Groq ---
57147
58148 [ TestMethod ]
@@ -63,6 +153,10 @@ public Task ChatClient_Groq_GetResponse() =>
63153 public Task ChatClient_Groq_Streaming ( ) =>
64154 ChatClient_CustomProvider_StreamingAsync ( CustomProvider . Groq ) ;
65155
156+ [ TestMethod ]
157+ public Task ChatClient_Groq_ToolCalling ( ) =>
158+ ChatClient_CustomProvider_ToolCallingAsync ( CustomProvider . Groq ) ;
159+
66160 // --- OpenRouter ---
67161
68162 [ TestMethod ]
@@ -73,6 +167,10 @@ public Task ChatClient_OpenRouter_GetResponse() =>
73167 public Task ChatClient_OpenRouter_Streaming ( ) =>
74168 ChatClient_CustomProvider_StreamingAsync ( CustomProvider . OpenRouter ) ;
75169
170+ [ TestMethod ]
171+ public Task ChatClient_OpenRouter_ToolCalling ( ) =>
172+ ChatClient_CustomProvider_ToolCallingAsync ( CustomProvider . OpenRouter ) ;
173+
76174 // --- Fireworks ---
77175
78176 [ TestMethod ]
@@ -83,6 +181,10 @@ public Task ChatClient_Fireworks_GetResponse() =>
83181 public Task ChatClient_Fireworks_Streaming ( ) =>
84182 ChatClient_CustomProvider_StreamingAsync ( CustomProvider . Fireworks ) ;
85183
184+ [ TestMethod ]
185+ public Task ChatClient_Fireworks_ToolCalling ( ) =>
186+ ChatClient_CustomProvider_ToolCallingAsync ( CustomProvider . Fireworks ) ;
187+
86188 // --- Together ---
87189
88190 [ TestMethod ]
@@ -93,6 +195,10 @@ public Task ChatClient_Together_GetResponse() =>
93195 public Task ChatClient_Together_Streaming ( ) =>
94196 ChatClient_CustomProvider_StreamingAsync ( CustomProvider . Together ) ;
95197
198+ [ TestMethod ]
199+ public Task ChatClient_Together_ToolCalling ( ) =>
200+ ChatClient_CustomProvider_ToolCallingAsync ( CustomProvider . Together ) ;
201+
96202 // --- DeepSeek ---
97203
98204 [ TestMethod ]
@@ -103,6 +209,10 @@ public Task ChatClient_DeepSeek_GetResponse() =>
103209 public Task ChatClient_DeepSeek_Streaming ( ) =>
104210 ChatClient_CustomProvider_StreamingAsync ( CustomProvider . DeepSeek ) ;
105211
212+ [ TestMethod ]
213+ public Task ChatClient_DeepSeek_ToolCalling ( ) =>
214+ ChatClient_CustomProvider_ToolCallingAsync ( CustomProvider . DeepSeek ) ;
215+
106216 // --- XAi (Grok) ---
107217
108218 [ TestMethod ]
@@ -113,7 +223,11 @@ public Task ChatClient_XAi_GetResponse() =>
113223 public Task ChatClient_XAi_Streaming ( ) =>
114224 ChatClient_CustomProvider_StreamingAsync ( CustomProvider . XAi ) ;
115225
116- // --- Perplexity ---
226+ [ TestMethod ]
227+ public Task ChatClient_XAi_ToolCalling ( ) =>
228+ ChatClient_CustomProvider_ToolCallingAsync ( CustomProvider . XAi ) ;
229+
230+ // --- Perplexity (no tool calling support) ---
117231
118232 [ TestMethod ]
119233 public Task ChatClient_Perplexity_GetResponse ( ) =>
@@ -133,6 +247,10 @@ public Task ChatClient_SambaNova_GetResponse() =>
133247 public Task ChatClient_SambaNova_Streaming ( ) =>
134248 ChatClient_CustomProvider_StreamingAsync ( CustomProvider . SambaNova ) ;
135249
250+ [ TestMethod ]
251+ public Task ChatClient_SambaNova_ToolCalling ( ) =>
252+ ChatClient_CustomProvider_ToolCallingAsync ( CustomProvider . SambaNova ) ;
253+
136254 // --- Mistral ---
137255
138256 [ TestMethod ]
@@ -143,6 +261,10 @@ public Task ChatClient_Mistral_GetResponse() =>
143261 public Task ChatClient_Mistral_Streaming ( ) =>
144262 ChatClient_CustomProvider_StreamingAsync ( CustomProvider . Mistral ) ;
145263
264+ [ TestMethod ]
265+ public Task ChatClient_Mistral_ToolCalling ( ) =>
266+ ChatClient_CustomProvider_ToolCallingAsync ( CustomProvider . Mistral ) ;
267+
146268 // --- Cerebras ---
147269
148270 [ TestMethod ]
@@ -153,6 +275,10 @@ public Task ChatClient_Cerebras_GetResponse() =>
153275 public Task ChatClient_Cerebras_Streaming ( ) =>
154276 ChatClient_CustomProvider_StreamingAsync ( CustomProvider . Cerebras ) ;
155277
278+ [ TestMethod ]
279+ public Task ChatClient_Cerebras_ToolCalling ( ) =>
280+ ChatClient_CustomProvider_ToolCallingAsync ( CustomProvider . Cerebras ) ;
281+
156282 // --- Cohere ---
157283
158284 [ TestMethod ]
@@ -163,6 +289,10 @@ public Task ChatClient_Cohere_GetResponse() =>
163289 public Task ChatClient_Cohere_Streaming ( ) =>
164290 ChatClient_CustomProvider_StreamingAsync ( CustomProvider . Cohere ) ;
165291
292+ [ TestMethod ]
293+ public Task ChatClient_Cohere_ToolCalling ( ) =>
294+ ChatClient_CustomProvider_ToolCallingAsync ( CustomProvider . Cohere ) ;
295+
166296 // --- Nebius ---
167297
168298 [ TestMethod ]
@@ -173,6 +303,10 @@ public Task ChatClient_Nebius_GetResponse() =>
173303 public Task ChatClient_Nebius_Streaming ( ) =>
174304 ChatClient_CustomProvider_StreamingAsync ( CustomProvider . Nebius ) ;
175305
306+ [ TestMethod ]
307+ public Task ChatClient_Nebius_ToolCalling ( ) =>
308+ ChatClient_CustomProvider_ToolCallingAsync ( CustomProvider . Nebius ) ;
309+
176310 // --- GitHub Models ---
177311
178312 [ TestMethod ]
@@ -182,4 +316,8 @@ public Task ChatClient_GitHub_GetResponse() =>
182316 [ TestMethod ]
183317 public Task ChatClient_GitHub_Streaming ( ) =>
184318 ChatClient_CustomProvider_StreamingAsync ( CustomProvider . GitHub ) ;
319+
320+ [ TestMethod ]
321+ public Task ChatClient_GitHub_ToolCalling ( ) =>
322+ ChatClient_CustomProvider_ToolCallingAsync ( CustomProvider . GitHub ) ;
185323}
0 commit comments