1- namespace Devlooped . Extensions . AI ;
2-
1+ using System . ClientModel . Primitives ;
2+ using System . Text . Json . Nodes ;
33using Microsoft . Extensions . AI ;
44using static ConfigurationExtensions ;
55
6- public class GrokTests
6+ namespace Devlooped . Extensions . AI ;
7+
8+ public class GrokTests ( ITestOutputHelper output )
79{
810 [ SecretsFact ( "XAI_API_KEY" ) ]
911 public async Task GrokInvokesTools ( )
@@ -23,12 +25,18 @@ public async Task GrokInvokesTools()
2325 Tools = [ AIFunctionFactory . Create ( ( ) => DateTimeOffset . Now . ToString ( "O" ) , "get_date" ) ]
2426 } ;
2527
26- var response = await grok . GetResponseAsync ( messages , options ) ;
28+ var client = grok . GetChatClient ( "grok-3" ) ;
29+ var chat = Assert . IsType < IChatClient > ( client , false ) ;
30+
31+ var response = await chat . GetResponseAsync ( messages , options ) ;
2732 var getdate = response . Messages
2833 . SelectMany ( x => x . Contents . OfType < FunctionCallContent > ( ) )
2934 . Any ( x => x . Name == "get_date" ) ;
3035
3136 Assert . True ( getdate ) ;
37+ // NOTE: the chat client was requested as grok-3 but the chat options wanted a
38+ // different model and the grok client honors that choice.
39+ Assert . Equal ( "grok-3-mini" , response . ModelId ) ;
3240 }
3341
3442 [ SecretsFact ( "XAI_API_KEY" ) ]
@@ -40,7 +48,11 @@ public async Task GrokInvokesToolAndSearch()
4048 { "user" , "What's Tesla stock worth today?" } ,
4149 } ;
4250
43- var grok = new GrokClient ( Configuration [ "XAI_API_KEY" ] ! )
51+ var transport = new TestPipelineTransport ( HttpClientPipelineTransport . Shared , output ) ;
52+
53+ var grok = new GrokClient ( Configuration [ "XAI_API_KEY" ] ! , new OpenAI . OpenAIClientOptions ( ) { Transport = transport } )
54+ . GetChatClient ( "grok-3" )
55+ . AsIChatClient ( )
4456 . AsBuilder ( )
4557 . UseFunctionInvocation ( )
4658 . Build ( ) ;
@@ -54,14 +66,30 @@ public async Task GrokInvokesToolAndSearch()
5466
5567 var response = await grok . GetResponseAsync ( messages , options ) ;
5668
69+ // assert that the request contains the following node
70+ // "search_parameters": {
71+ // "mode": "on"
72+ //}
73+ Assert . All ( transport . Requests , x =>
74+ {
75+ var search = Assert . IsType < JsonObject > ( x [ "search_parameters" ] ) ;
76+ Assert . Equal ( "on" , search [ "mode" ] ? . GetValue < string > ( ) ) ;
77+ } ) ;
78+
5779 // The get_date result shows up as a tool role
5880 Assert . Contains ( response . Messages , x => x . Role == ChatRole . Tool ) ;
5981
60- var text = response . Text ;
82+ // Citations include nasdaq.com at least as a web search source
83+ var node = transport . Responses . LastOrDefault ( ) ;
84+ Assert . NotNull ( node ) ;
85+ var citations = Assert . IsType < JsonArray > ( node [ "citations" ] , false ) ;
86+ var yahoo = citations . Where ( x => x != null ) . Any ( x => x ! . ToString ( ) . Contains ( "https://finance.yahoo.com/quote/TSLA/" , StringComparison . Ordinal ) ) ;
6187
62- Assert . Contains ( "TSLA" , text ) ;
63- Assert . Contains ( "$" , text ) ;
64- Assert . Contains ( "Nasdaq" , text , StringComparison . OrdinalIgnoreCase ) ;
88+ Assert . True ( yahoo , "Expected at least one citation to nasdaq.com" ) ;
89+
90+ // NOTE: the chat client was requested as grok-3 but the chat options wanted a
91+ // different model and the grok client honors that choice.
92+ Assert . Equal ( "grok-3-mini" , response . ModelId ) ;
6593 }
6694
6795 [ SecretsFact ( "XAI_API_KEY" ) ]
@@ -73,20 +101,43 @@ public async Task GrokInvokesHostedSearchTool()
73101 { "user" , "What's Tesla stock worth today? Search X and the news for latest info." } ,
74102 } ;
75103
76- var grok = new GrokClient ( Configuration [ "XAI_API_KEY" ] ! ) ;
104+ var transport = new TestPipelineTransport ( HttpClientPipelineTransport . Shared , output ) ;
105+
106+ var grok = new GrokClient ( Configuration [ "XAI_API_KEY" ] ! , new OpenAI . OpenAIClientOptions ( ) { Transport = transport } ) ;
107+ var client = grok . GetChatClient ( "grok-3" ) ;
108+ var chat = Assert . IsType < IChatClient > ( client , false ) ;
77109
78110 var options = new ChatOptions
79111 {
80- ModelId = "grok-3" ,
81112 Tools = [ new HostedWebSearchTool ( ) ]
82113 } ;
83114
84- var response = await grok . GetResponseAsync ( messages , options ) ;
115+ var response = await chat . GetResponseAsync ( messages , options ) ;
85116 var text = response . Text ;
86117
87118 Assert . Contains ( "TSLA" , text ) ;
88- Assert . Contains ( "$" , text ) ;
89- Assert . Contains ( "Nasdaq" , text , StringComparison . OrdinalIgnoreCase ) ;
119+
120+ // assert that the request contains the following node
121+ // "search_parameters": {
122+ // "mode": "auto"
123+ //}
124+ Assert . All ( transport . Requests , x =>
125+ {
126+ var search = Assert . IsType < JsonObject > ( x [ "search_parameters" ] ) ;
127+ Assert . Equal ( "auto" , search [ "mode" ] ? . GetValue < string > ( ) ) ;
128+ } ) ;
129+
130+ // Citations include nasdaq.com at least as a web search source
131+ Assert . Single ( transport . Responses ) ;
132+ var node = transport . Responses [ 0 ] ;
133+ Assert . NotNull ( node ) ;
134+ var citations = Assert . IsType < JsonArray > ( node [ "citations" ] , false ) ;
135+ var yahoo = citations . Where ( x => x != null ) . Any ( x => x ! . ToString ( ) . Contains ( "https://finance.yahoo.com/quote/TSLA/" , StringComparison . Ordinal ) ) ;
136+
137+ Assert . True ( yahoo , "Expected at least one citation to nasdaq.com" ) ;
138+
139+ // Uses the default model set by the client when we asked for it
140+ Assert . Equal ( "grok-3" , response . ModelId ) ;
90141 }
91142
92143 [ SecretsFact ( "XAI_API_KEY" ) ]
@@ -99,6 +150,8 @@ public async Task GrokThinksHard()
99150 } ;
100151
101152 var grok = new GrokClient ( Configuration [ "XAI_API_KEY" ] ! )
153+ . GetChatClient ( "grok-3" )
154+ . AsIChatClient ( )
102155 . AsBuilder ( )
103156 . UseFunctionInvocation ( )
104157 . Build ( ) ;
@@ -115,5 +168,8 @@ public async Task GrokThinksHard()
115168 var text = response . Text ;
116169
117170 Assert . Contains ( "48 years" , text ) ;
171+ // NOTE: the chat client was requested as grok-3 but the chat options wanted a
172+ // different model and the grok client honors that choice.
173+ Assert . StartsWith ( "grok-3-mini" , response . ModelId ) ;
118174 }
119175}
0 commit comments