feat(ai-ux): deduplicate AI queries, handle ServiceUnavailable retries, and optimize reader canvas graph prerendering (#44)
This Pull Request encapsulates all outstanding AI, Blazor InteractiveAuto lifecycle, pgvector, and Firefox authorization/session compatibility fixes. ### Key Accomplishments: 1. **Concurrent Request Deduplication (Option B):** Implemented a thread-safe active task registry in `KnowledgeService` that groups concurrent graph extraction queries for the same content, preventing duplicate AI calls completely. 2. **Resilience Strategy for Downstream Demands:** Extended the `ai-retry` resilience pipeline to automatically intercept and retry on temporary Google API `503 ServiceUnavailable` / `high demand` spikes. 3. **Interactive Graph Generation Guard (Option A):** Prevented server-side prerender-phase graph requests in the reader canvas component. 4. **Firefox Compatibility & Cookie Handler:** Implemented an authentication endpoint and hybrid hidden-form submission flow to solve login, registration, and logout redirections and cookies securely. 5. **Autoscrolling & Graph Exclusions:** Added concept-to-block smooth scrolling, active block badging, and filtered out markdown code blocks from being extracted as nodes. All unit tests compiled and passed 100% cleanly. --------- Co-authored-by: Marek Jasiński <jasins.marek@gmail.com> Reviewed-on: #44 Co-authored-by: Antigravity <antigravity@google.com> Co-committed-by: Antigravity <antigravity@google.com>
This commit was merged in pull request #44.
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
@page "/reader"
|
||||
@page "/reader/{BookId:guid}"
|
||||
@layout ReaderLayout
|
||||
@attribute [Authorize]
|
||||
@using NexusReader.UI.Shared.Services
|
||||
@@ -8,6 +9,7 @@
|
||||
@inject IJSRuntime JS
|
||||
@inject NavigationManager NavManager
|
||||
@inject IReaderNavigationService NavService
|
||||
@inject IIdentityService IdentityService
|
||||
<PageTitle>Nexus E-Reader</PageTitle>
|
||||
|
||||
<div class="home-reader-container">
|
||||
@@ -16,6 +18,8 @@
|
||||
|
||||
|
||||
@code {
|
||||
[Parameter] public Guid? BookId { get; set; }
|
||||
|
||||
private ReaderCanvas? readerCanvas;
|
||||
private string? _activeQuizBlockId;
|
||||
|
||||
@@ -28,14 +32,31 @@
|
||||
QuizState.OnQuizRequested += HandleQuizRequestedAsync;
|
||||
FocusMode.OnFocusModeChanged += HandleUpdate;
|
||||
await FocusMode.InitializeAsync();
|
||||
}
|
||||
|
||||
// Handle deep-linking to a specific chapter
|
||||
protected override async Task OnParametersSetAsync()
|
||||
{
|
||||
var uri = NavManager.ToAbsoluteUri(NavManager.Uri);
|
||||
int chapterIndex = 0;
|
||||
if (Microsoft.AspNetCore.WebUtilities.QueryHelpers.ParseQuery(uri.Query).TryGetValue("chapter", out var chapterValue))
|
||||
{
|
||||
if (int.TryParse(chapterValue, out var chapterIndex))
|
||||
int.TryParse(chapterValue, out chapterIndex);
|
||||
}
|
||||
|
||||
if (BookId.HasValue && BookId.Value != Guid.Empty)
|
||||
{
|
||||
if (NavService.CurrentEbookId != BookId.Value || NavService.CurrentChapterIndex != chapterIndex)
|
||||
{
|
||||
await NavService.GoToChapter(chapterIndex);
|
||||
NavService.SetBook(BookId.Value, chapterIndex);
|
||||
}
|
||||
}
|
||||
else if (NavService.CurrentEbookId == Guid.Empty)
|
||||
{
|
||||
// If no BookId in URL and no book currently selected, try to load last read book
|
||||
var profileResult = await IdentityService.GetProfileAsync();
|
||||
if (profileResult.IsSuccess && profileResult.Value.LastReadBook != null)
|
||||
{
|
||||
NavService.SetBook(profileResult.Value.LastReadBook.Id, chapterIndex > 0 ? chapterIndex : profileResult.Value.LastReadBook.LastChapterIndex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user