1+ using System . Net . Http . Json ;
2+ using System . Text . Json . Serialization ;
3+ using Devlooped . Extensions . AI . OpenAI ;
4+ using OpenTelemetry . Metrics ;
5+ using OpenTelemetry . Trace ;
6+ using Spectre . Console ;
7+
8+ var builder = App . CreateBuilder ( args ) ;
9+ #if DEBUG
10+ builder . Environment . EnvironmentName = Environments . Development ;
11+ #endif
12+
13+ builder . AddServiceDefaults ( ) ;
14+ builder . Services . AddHttpClient ( ) ;
15+
16+ var app = builder . Build ( async ( IServiceProvider services , CancellationToken cancellation ) =>
17+ {
18+ var baseUrl = Environment . GetEnvironmentVariable ( "applicationUrl" ) ?? "http://localhost:5117" ;
19+ var http = services . GetRequiredService < IHttpClientFactory > ( ) . CreateClient ( ) ;
20+ var agents = await http . GetFromJsonAsync < AgentCard [ ] > ( $ "{ baseUrl } /agents", cancellation ) ?? [ ] ;
21+
22+ if ( agents . Length == 0 )
23+ {
24+ AnsiConsole . MarkupLine ( ":warning: No agents available" ) ;
25+ return ;
26+ }
27+
28+ var selectedAgent = AnsiConsole . Prompt ( new SelectionPrompt < AgentCard > ( )
29+ . Title ( "Select agent:" )
30+ . UseConverter ( a => $ "{ a . Name } : { a . Description ?? "" } ")
31+ . AddChoices ( agents ) ) ;
32+
33+ var chat = new OpenAIChatClient ( "none" , "default" , new OpenAI . OpenAIClientOptions
34+ {
35+ Endpoint = new Uri ( $ "{ baseUrl } /{ selectedAgent . Name } /v1")
36+ } ) . AsBuilder ( ) . UseOpenTelemetry ( ) . UseJsonConsoleLogging ( ) . Build ( services ) ;
37+
38+ var history = new List < ChatMessage > ( ) ;
39+
40+ AnsiConsole . MarkupLine ( $ ":robot: Ready") ;
41+ AnsiConsole . Markup ( $ ":person_beard: ") ;
42+ while ( ! cancellation . IsCancellationRequested )
43+ {
44+ var input = Console . ReadLine ( ) ? . Trim ( ) ;
45+ if ( string . IsNullOrEmpty ( input ) )
46+ continue ;
47+
48+ history . Add ( new ChatMessage ( ChatRole . User , input ) ) ;
49+ try
50+ {
51+ var response = await AnsiConsole . Status ( ) . StartAsync ( ":robot: Thinking..." , ctx => chat . GetResponseAsync ( input ) ) ;
52+ history . AddRange ( response . Messages ) ;
53+ try
54+ {
55+ // Try rendering as formatted markup
56+ if ( response . Text is { Length : > 0 } )
57+ AnsiConsole . MarkupLine ( $ ":robot: { response . Text } ") ;
58+ }
59+ catch ( Exception )
60+ {
61+ // Fallback to escaped markup text if rendering fails
62+ AnsiConsole . MarkupLineInterpolated ( $ ":robot: { response . Text } ") ;
63+ }
64+ AnsiConsole . Markup ( $ ":person_beard: ") ;
65+ }
66+ catch ( Exception e )
67+ {
68+ AnsiConsole . WriteException ( e ) ;
69+ }
70+ }
71+
72+ AnsiConsole . MarkupLine ( $ ":robot: Shutting down...") ;
73+ } ) ;
74+
75+ Console . WriteLine ( "Powered by Smith" ) ;
76+
77+ await app . RunAsync ( ) ;
78+
79+ record AgentCard ( string Name , string ? Description ) ;
0 commit comments