feat(intelligence): implement global hybrid search engine and monetization logic

- Created IUserLibraryStore and IVectorSearchStore abstractions to decouple relational DB and Qdrant gRPC logic from Application Layer
- Implemented MediatR GetGlobalIntelligenceQuery with value-first teaser RAG monetization logic
- Registered new request and response DTOs in AppJsonContext for Native AOT source-generated serialization
- Bound RagMonetizationOptions via IOptions pattern in appsettings.json configuration
- Added POST /api/intelligence endpoint on server and implemented GetGlobalIntelligenceAsync in WASM client service
- Refactored Intelligence.razor to consume the backend-driven global hybrid search Q&A engine
This commit is contained in:
2026-06-06 10:55:58 +02:00
parent faf6ec826e
commit 93133a49b6
15 changed files with 692 additions and 43 deletions
@@ -2,6 +2,7 @@ using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Configuration;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.AI;
using NexusReader.Application.Common;
using GeminiDotnet;
using GeminiDotnet.Extensions.AI;
using NexusReader.Data.Persistence;
@@ -76,6 +77,7 @@ public static class DependencyInjection
services.Configure<AiSettings>(configuration.GetSection(AiSettings.SectionName));
services.Configure<StripeSettings>(configuration.GetSection(StripeSettings.SectionName));
services.Configure<RagMonetizationOptions>(configuration.GetSection(RagMonetizationOptions.SectionName));
var aiSettings = configuration.GetSection(AiSettings.SectionName).Get<AiSettings>() ?? new AiSettings();
if (string.IsNullOrWhiteSpace(aiSettings.ApiKey) || aiSettings.ApiKey == "PLACEHOLDER")
@@ -127,6 +129,8 @@ public static class DependencyInjection
services.AddScoped<IEbookRepository, EbookRepository>();
services.AddScoped<IQuizResultRepository, QuizResultRepository>();
services.AddScoped<IConceptsMapReadRepository, ConceptsMapReadRepository>();
services.AddScoped<IUserLibraryStore, UserLibraryStore>();
services.AddScoped<IVectorSearchStore, VectorSearchStore>();
// Fix #2: SignalR broadcaster (scoped, wraps IHubContext which is itself a singleton wrapper)
services.AddScoped<ISyncBroadcaster, SignalRSyncBroadcaster>();