using Microsoft.AspNetCore.Server.Kestrel.Core; using Microsoft.Extensions.AI; using Svrnty.CQRS; using Svrnty.CQRS.FluentValidation; using Svrnty.CQRS.Grpc; using Svrnty.Sample; using Svrnty.Sample.AI; using Svrnty.Sample.AI.Commands; using Svrnty.CQRS.MinimalApi; using Svrnty.CQRS.DynamicQuery; using Svrnty.CQRS.Abstractions; var builder = WebApplication.CreateBuilder(args); // Configure Kestrel to support both HTTP/1.1 (for REST APIs) and HTTP/2 (for gRPC) builder.WebHost.ConfigureKestrel(options => { // Port 6000: HTTP/2 for gRPC options.ListenLocalhost(6000, o => o.Protocols = HttpProtocols.Http2); // Port 6001: HTTP/1.1 for HTTP API options.ListenLocalhost(6001, o => o.Protocols = HttpProtocols.Http1); }); // IMPORTANT: Register dynamic query dependencies FIRST // (before AddSvrntyCqrs, so gRPC services can find the handlers) builder.Services.AddTransient(); builder.Services.AddTransient(); builder.Services.AddDynamicQueryWithProvider(); // Register Ollama AI client builder.Services.AddHttpClient(client => { client.BaseAddress = new Uri("http://localhost:11434"); }); // Register commands and queries with validators builder.Services.AddCommand(); builder.Services.AddCommand(); builder.Services.AddQuery(); // Register AI agent command builder.Services.AddCommand(); // Configure CQRS with fluent API builder.Services.AddSvrntyCqrs(cqrs => { // Enable gRPC endpoints with reflection cqrs.AddGrpc(grpc => { grpc.EnableReflection(); }); // Enable MinimalApi endpoints cqrs.AddMinimalApi(configure => { }); }); builder.Services.AddEndpointsApiExplorer(); builder.Services.AddSwaggerGen(); var app = builder.Build(); // Map all configured CQRS endpoints (gRPC, MinimalApi, and Dynamic Queries) app.UseSvrntyCqrs(); app.UseSwagger(); app.UseSwaggerUI(); // Health check endpoints app.MapGet("/health", () => Results.Ok(new { status = "healthy" })) .WithTags("Health"); app.MapGet("/health/ready", async (IChatClient client) => { try { var testMessages = new List { new(ChatRole.User, "ping") }; var response = await client.CompleteAsync(testMessages); return Results.Ok(new { status = "ready", ollama = "connected", responseTime = response != null ? "ok" : "slow" }); } catch (Exception ex) { return Results.Json(new { status = "not_ready", ollama = "disconnected", error = ex.Message }, statusCode: 503); } }) .WithTags("Health"); Console.WriteLine("Auto-Generated gRPC Server with Reflection, Validation, MinimalApi and Swagger"); Console.WriteLine("gRPC (HTTP/2): http://localhost:6000"); Console.WriteLine("HTTP API (HTTP/1.1): http://localhost:6001/api/command/* and http://localhost:6001/api/query/*"); Console.WriteLine("Swagger UI: http://localhost:6001/swagger"); app.Run();