# Intelligence

- File ID: file:1kjntt:intelligence-razor
- Path: NexusReader.UI.Shared/Pages/Intelligence.razor
- Role: ui-page
- Layer: frontend

## Purpose

Razor UI page providing a client-side interface for asking AI questions against the user's library (Global AI Q&A); binds input, loads book scope, calls the knowledge service, and renders answers with grounded citations.

## Key Details

UI binds _question and _selectedBookId; loads books on init; AskQuestionAsync enforces single concurrent request, parses optional book Guid, calls IKnowledgeService.AskQuestionAsync, and renders answer + grounded citations with explicit error fallbacks.

## Symbols

- OnInitializedAsync(): Initializes the component by loading recent books for the scope selector from the API.
- HandleKeyUp(): Handles key up events on the input; triggers AskQuestionAsync when Enter is pressed and input is non-empty and not loading.
- AskQuestionAsync(): Orchestrates asking the knowledge service a question: validates input, sets loading state, optionally scopes by book, calls IKnowledgeService, handles success/error responses and exceptions, and clears loading state.

## Dependencies

- No resolved dependencies.

## Calls

- No resolved calls.

## Unresolved References

- dependency-target: NexusReader.Application.Abstractions/Services/IKnowledgeService.cs
- dependency-target: NexusReader.Application.DTOs.AI/GroundedResponseDto.cs
- dependency-target: NexusReader.Application.DTOs.AI/CitationDto.cs
- dependency-target: NexusReader.Application.DTOs.User/LastReadBookDto.cs
- call-target: self
- call-target: NexusReader.Application.Abstractions/Services/IKnowledgeService.cs
- interaction-target: Answer = $"Error: {result.Errors.FirstOrDefault()?.Message ?? "An error occurred."}",
- interaction-target: await Http.GetFromJsonAsync<List<LastReadBookDto>>("api/library/books") assigns to _books
- interaction-target: await KnowledgeService.AskQuestionAsync(_question, "tenantId", ebookId)

## Coverage

- Symbols: 3
- Executable symbols: 3
- Executable symbols with control flow: 3
- Grounded edges: 3
- Unresolved references: 9
- Control-flow fragments: 3
- Unresolved jumps: 1
- Unsupported constructs: 0
- Control-flow coverage: 100%
- Required diagrams: 2
- Generated diagrams: 5

## Control Flow Fragments

- OnInitializedAsync: 7 nodes, 6 edges, 0 jumps, 0 unsupported constructs
- HandleKeyUp: 12 nodes, 13 edges, 1 jumps, 0 unsupported constructs
- AskQuestionAsync: 40 nodes, 46 edges, 1 jumps, 0 unsupported constructs

## Diagrams

### Intelligence Neighborhood

```mermaid
flowchart LR
    file_1kjntt_intelligence_razor("Intelligence")
    method_1f4bu99_oninitializedasync[["OnInitializedAsync()"]]
    method_91tjy5_handlekeyup[["HandleKeyUp()"]]
    method_c84ulg_askquestionasync[["AskQuestionAsync()"]]
```

### Intelligence Execution Overview

```mermaid
flowchart TD
    file_1kjntt_intelligence_razor("Intelligence")
    method_1f4bu99_oninitializedasync[["OnInitializedAsync()"]]
    method_91tjy5_handlekeyup[["HandleKeyUp()"]]
    method_c84ulg_askquestionasync[["AskQuestionAsync()"]]
    unresolved_unresolved_11npc0r_interaction_target{"Unresolved: Answer = $\\"Error: {result.Errors.FirstOrDefault()?.Message ?? \\"An error occurred.\\"}\\","}
    unresolved_unresolved_17572gj_call_target{"Unresolved: AskQuestionAsync"}
    unresolved_unresolved_1to7exj_interaction_target{"Unresolved: await KnowledgeService.AskQuestionAsync(_question, \\"tenantId\\", ebookId)"}
    unresolved_unresolved_1wagwxf_interaction_target{"Unresolved: await Http.GetFromJsonAsync<List<LastReadBookDto>>(\\"api/library/books\\") assigns to _books"}
    unresolved_unresolved_k85jvs_call_target{"Unresolved: AskQuestionAsync"}
    file_1kjntt_intelligence_razor -->|contains| method_1f4bu99_oninitializedasync
    file_1kjntt_intelligence_razor -->|contains| method_91tjy5_handlekeyup
    file_1kjntt_intelligence_razor -->|contains| method_c84ulg_askquestionasync
    file_1kjntt_intelligence_razor -->|unresolved interaction| unresolved_unresolved_11npc0r_interaction_target
    file_1kjntt_intelligence_razor -->|unresolved interaction| unresolved_unresolved_1to7exj_interaction_target
    file_1kjntt_intelligence_razor -->|unresolved interaction| unresolved_unresolved_1wagwxf_interaction_target
    method_91tjy5_handlekeyup -->|unresolved call| unresolved_unresolved_17572gj_call_target
    method_c84ulg_askquestionasync -->|unresolved call| unresolved_unresolved_k85jvs_call_target
```

### OnInitializedAsync() Control Flow

```mermaid
flowchart TD
    method_1f4bu99_oninitializedasync__action_390_oninitializedasync_try_390_0__try("Begins protected execution")
    method_1f4bu99_oninitializedasync__action_390_try_catch_390__linear("Swallow errors loading books")
    method_1f4bu99_oninitializedasync__action_392_oninitializedasync_await_392_1__await[["Waits for async work"]]
    method_1f4bu99_oninitializedasync__action_394_oninitializedasync_catch_394_2__catch("catch Exception ex")
    method_1f4bu99_oninitializedasync__entry(["OnInitializedAsync entry"])
    method_1f4bu99_oninitializedasync__action_392_external_call_392__linear("Load books for scope selector")
    method_1f4bu99_oninitializedasync__implicit_return(["return"])
    method_1f4bu99_oninitializedasync__action_390_oninitializedasync_try_390_0__try -->|next| method_1f4bu99_oninitializedasync__action_392_oninitializedasync_await_392_1__await
    method_1f4bu99_oninitializedasync__action_390_try_catch_390__linear -->|next| method_1f4bu99_oninitializedasync__action_390_oninitializedasync_try_390_0__try
    method_1f4bu99_oninitializedasync__action_392_external_call_392__linear -->|exception| method_1f4bu99_oninitializedasync__action_394_oninitializedasync_catch_394_2__catch
    method_1f4bu99_oninitializedasync__action_392_oninitializedasync_await_392_1__await -->|next| method_1f4bu99_oninitializedasync__action_392_external_call_392__linear
    method_1f4bu99_oninitializedasync__action_394_oninitializedasync_catch_394_2__catch -->|return| method_1f4bu99_oninitializedasync__implicit_return
    method_1f4bu99_oninitializedasync__entry -->|next| method_1f4bu99_oninitializedasync__action_390_try_catch_390__linear
```

### HandleKeyUp() Control Flow

```mermaid
flowchart TD
    method_91tjy5_handlekeyup__call_404_AskQuestionAsync[["AskQuestionAsync"]]
    method_91tjy5_handlekeyup__action_402_guard_clause_402__condition{"e.Key == \\"Enter\\" && !string.IsNullOrWhiteSpace(_question) && !_isLoading"}
    method_91tjy5_handlekeyup__action_402_guard_clause_402__false("no-op")
    method_91tjy5_handlekeyup__action_402_guard_clause_402__merge("merge")
    method_91tjy5_handlekeyup__action_402_guard_clause_402__true("call-AskQuestionAsync")
    method_91tjy5_handlekeyup__action_402_handlekeyup_branch_402_0__condition{"e.Key == \\"Enter\\" && !string.IsNullOrWhiteSpace(_question) && !_isLoading"}
    method_91tjy5_handlekeyup__action_402_handlekeyup_branch_402_0__false("false")
    method_91tjy5_handlekeyup__action_402_handlekeyup_branch_402_0__merge("merge")
    method_91tjy5_handlekeyup__action_402_handlekeyup_branch_402_0__true("true")
    method_91tjy5_handlekeyup__action_404_handlekeyup_await_404_1__await[["Waits for async work"]]
    method_91tjy5_handlekeyup__entry(["HandleKeyUp entry"])
    method_91tjy5_handlekeyup__implicit_return(["return"])
    method_91tjy5_handlekeyup__action_402_guard_clause_402__condition -->|no-op| method_91tjy5_handlekeyup__action_402_guard_clause_402__false
    method_91tjy5_handlekeyup__action_402_guard_clause_402__condition -->|call-AskQuestionAsync| method_91tjy5_handlekeyup__action_402_guard_clause_402__true
    method_91tjy5_handlekeyup__action_402_guard_clause_402__false -->|next| method_91tjy5_handlekeyup__action_402_guard_clause_402__merge
    method_91tjy5_handlekeyup__action_402_guard_clause_402__merge -->|next| method_91tjy5_handlekeyup__action_402_handlekeyup_branch_402_0__condition
    method_91tjy5_handlekeyup__action_402_guard_clause_402__true -->|next| method_91tjy5_handlekeyup__action_402_guard_clause_402__merge
    method_91tjy5_handlekeyup__action_402_handlekeyup_branch_402_0__condition -->|false| method_91tjy5_handlekeyup__action_402_handlekeyup_branch_402_0__false
    method_91tjy5_handlekeyup__action_402_handlekeyup_branch_402_0__condition -->|true| method_91tjy5_handlekeyup__action_402_handlekeyup_branch_402_0__true
    method_91tjy5_handlekeyup__action_402_handlekeyup_branch_402_0__false -->|next| method_91tjy5_handlekeyup__action_402_handlekeyup_branch_402_0__merge
    method_91tjy5_handlekeyup__action_402_handlekeyup_branch_402_0__merge -->|next| method_91tjy5_handlekeyup__action_404_handlekeyup_await_404_1__await
    method_91tjy5_handlekeyup__action_402_handlekeyup_branch_402_0__true -->|next| method_91tjy5_handlekeyup__action_402_handlekeyup_branch_402_0__merge
    method_91tjy5_handlekeyup__action_404_handlekeyup_await_404_1__await -->|none| method_91tjy5_handlekeyup__call_404_AskQuestionAsync
    method_91tjy5_handlekeyup__call_404_AskQuestionAsync -->|return| method_91tjy5_handlekeyup__implicit_return
    method_91tjy5_handlekeyup__entry -->|next| method_91tjy5_handlekeyup__action_402_guard_clause_402__condition
```

### AskQuestionAsync() Control Flow

_Warnings: diagram method_c84ulg_askquestionasync__fragment_diagram exceeds preferred complexity thresholds (40 nodes, 46 edges)._

```mermaid
---
config:
  flowchart:
    defaultRenderer: "elk"
---
flowchart TD
    method_c84ulg_askquestionasync__call_425_AskQuestionAsync[["AskQuestionAsync"]]
    method_c84ulg_askquestionasync__action_410_askquestionasync_guard_clause_410_0__condition{"string.IsNullOrWhiteSpace(_question) || _isLoading"}
    method_c84ulg_askquestionasync__action_410_askquestionasync_guard_clause_410_0__false("continue")
    method_c84ulg_askquestionasync__action_410_askquestionasync_guard_clause_410_0__merge("merge")
    method_c84ulg_askquestionasync__action_410_askquestionasync_guard_clause_410_0__true("exit")
    method_c84ulg_askquestionasync__action_410_guard_clause_410__condition{"string.IsNullOrWhiteSpace(_question) || _isLoading"}
    method_c84ulg_askquestionasync__action_410_guard_clause_410__false("continue")
    method_c84ulg_askquestionasync__action_410_guard_clause_410__merge("merge")
    method_c84ulg_askquestionasync__action_410_guard_clause_410__true("return")
    method_c84ulg_askquestionasync__action_412_state_change_412__linear("Enter search state")
    method_c84ulg_askquestionasync__action_417_askquestionasync_try_417_1__try("Begins protected execution")
    method_c84ulg_askquestionasync__action_417_try_catch_417__linear("Catch network/API exceptions")
    method_c84ulg_askquestionasync__action_419_branch_419__condition{"!string.IsNullOrEmpty(_selectedBookId) && Guid.TryParse(_selectedBookId, out parsedId)"}
    method_c84ulg_askquestionasync__action_419_branch_419__false("ebookId null")
    method_c84ulg_askquestionasync__action_419_branch_419__merge("merge")
    method_c84ulg_askquestionasync__action_419_branch_419__true("ebookId set")
    method_c84ulg_askquestionasync__action_420_askquestionasync_branch_420_2__condition{"!string.IsNullOrEmpty(_selectedBookId) && Guid.TryParse(_selectedBookId, out var parsedId)"}
    method_c84ulg_askquestionasync__action_420_askquestionasync_branch_420_2__false("false")
    method_c84ulg_askquestionasync__action_420_askquestionasync_branch_420_2__merge("merge")
    method_c84ulg_askquestionasync__action_420_askquestionasync_branch_420_2__true("true")
    method_c84ulg_askquestionasync__action_425_askquestionasync_await_425_3__await[["Waits for async work"]]
    method_c84ulg_askquestionasync__action_426_askquestionasync_branch_426_4__condition{"result.IsSuccess"}
    method_c84ulg_askquestionasync__action_426_askquestionasync_branch_426_4__false("false")
    method_c84ulg_askquestionasync__action_426_askquestionasync_branch_426_4__merge("merge")
    method_c84ulg_askquestionasync__action_426_askquestionasync_branch_426_4__true("true")
    method_c84ulg_askquestionasync__action_426_branch_426__condition{"result.IsSuccess"}
    method_c84ulg_askquestionasync__action_426_branch_426__false("construct error GroundedResponseDto with first error message")
    method_c84ulg_askquestionasync__action_426_branch_426__merge("merge")
    method_c84ulg_askquestionasync__action_426_branch_426__true("assign response from result.Value")
    method_c84ulg_askquestionasync__action_430_askquestionasync_fallback_430_5__condition{"Falls back to alternate path"}
    method_c84ulg_askquestionasync__action_430_askquestionasync_fallback_430_5__false("otherwise")
    method_c84ulg_askquestionasync__action_430_askquestionasync_fallback_430_5__merge("merge")
    method_c84ulg_askquestionasync__action_430_askquestionasync_fallback_430_5__true("fallback")
    method_c84ulg_askquestionasync__action_439_askquestionasync_catch_439_7__catch("catch Exception ex")
    method_c84ulg_askquestionasync__action_447_askquestionasync_finally_447_8__finally("Runs cleanup or finalization")
    method_c84ulg_askquestionasync__action_447_finally_447__finally("Exit loading state and refresh UI")
    method_c84ulg_askquestionasync__entry(["AskQuestionAsync entry"])
    method_c84ulg_askquestionasync__action_425_external_call_425__linear("Ask knowledge service")
    method_c84ulg_askquestionasync__action_434_askquestionasync_repository_read_434_6__linear[("Reads repository or persistence state")]
    method_c84ulg_askquestionasync__implicit_return(["return"])
    method_c84ulg_askquestionasync__action_410_askquestionasync_guard_clause_410_0__condition -->|continue| method_c84ulg_askquestionasync__action_410_askquestionasync_guard_clause_410_0__false
    method_c84ulg_askquestionasync__action_410_askquestionasync_guard_clause_410_0__condition -->|exit| method_c84ulg_askquestionasync__action_410_askquestionasync_guard_clause_410_0__true
    method_c84ulg_askquestionasync__action_410_askquestionasync_guard_clause_410_0__false -->|next| method_c84ulg_askquestionasync__action_410_askquestionasync_guard_clause_410_0__merge
    method_c84ulg_askquestionasync__action_410_askquestionasync_guard_clause_410_0__merge -->|next| method_c84ulg_askquestionasync__action_412_state_change_412__linear
    method_c84ulg_askquestionasync__action_410_askquestionasync_guard_clause_410_0__true -->|next| method_c84ulg_askquestionasync__action_410_askquestionasync_guard_clause_410_0__merge
    method_c84ulg_askquestionasync__action_410_guard_clause_410__condition -->|continue| method_c84ulg_askquestionasync__action_410_guard_clause_410__false
    method_c84ulg_askquestionasync__action_410_guard_clause_410__condition -->|return| method_c84ulg_askquestionasync__action_410_guard_clause_410__true
    method_c84ulg_askquestionasync__action_410_guard_clause_410__false -->|next| method_c84ulg_askquestionasync__action_410_guard_clause_410__merge
    method_c84ulg_askquestionasync__action_410_guard_clause_410__merge -->|next| method_c84ulg_askquestionasync__action_410_askquestionasync_guard_clause_410_0__condition
    method_c84ulg_askquestionasync__action_410_guard_clause_410__true -->|next| method_c84ulg_askquestionasync__action_410_guard_clause_410__merge
    method_c84ulg_askquestionasync__action_412_state_change_412__linear -->|next| method_c84ulg_askquestionasync__action_417_try_catch_417__linear
    method_c84ulg_askquestionasync__action_417_askquestionasync_try_417_1__try -->|next| method_c84ulg_askquestionasync__action_419_branch_419__condition
    method_c84ulg_askquestionasync__action_417_try_catch_417__linear -->|next| method_c84ulg_askquestionasync__action_417_askquestionasync_try_417_1__try
    method_c84ulg_askquestionasync__action_419_branch_419__condition -->|ebookId null| method_c84ulg_askquestionasync__action_419_branch_419__false
    method_c84ulg_askquestionasync__action_419_branch_419__condition -->|ebookId set| method_c84ulg_askquestionasync__action_419_branch_419__true
    method_c84ulg_askquestionasync__action_419_branch_419__false -->|next| method_c84ulg_askquestionasync__action_419_branch_419__merge
    method_c84ulg_askquestionasync__action_419_branch_419__merge -->|next| method_c84ulg_askquestionasync__action_420_askquestionasync_branch_420_2__condition
    method_c84ulg_askquestionasync__action_419_branch_419__true -->|next| method_c84ulg_askquestionasync__action_419_branch_419__merge
    method_c84ulg_askquestionasync__action_420_askquestionasync_branch_420_2__condition -->|false| method_c84ulg_askquestionasync__action_420_askquestionasync_branch_420_2__false
    method_c84ulg_askquestionasync__action_420_askquestionasync_branch_420_2__condition -->|true| method_c84ulg_askquestionasync__action_420_askquestionasync_branch_420_2__true
    method_c84ulg_askquestionasync__action_420_askquestionasync_branch_420_2__false -->|next| method_c84ulg_askquestionasync__action_420_askquestionasync_branch_420_2__merge
    method_c84ulg_askquestionasync__action_420_askquestionasync_branch_420_2__merge -->|next| method_c84ulg_askquestionasync__action_425_askquestionasync_await_425_3__await
    method_c84ulg_askquestionasync__action_420_askquestionasync_branch_420_2__true -->|next| method_c84ulg_askquestionasync__action_420_askquestionasync_branch_420_2__merge
    method_c84ulg_askquestionasync__action_425_askquestionasync_await_425_3__await -->|next| method_c84ulg_askquestionasync__action_425_external_call_425__linear
    method_c84ulg_askquestionasync__action_425_external_call_425__linear -->|calls| method_c84ulg_askquestionasync__call_425_AskQuestionAsync
    method_c84ulg_askquestionasync__action_426_askquestionasync_branch_426_4__condition -->|false| method_c84ulg_askquestionasync__action_426_askquestionasync_branch_426_4__false
    method_c84ulg_askquestionasync__action_426_askquestionasync_branch_426_4__condition -->|true| method_c84ulg_askquestionasync__action_426_askquestionasync_branch_426_4__true
    method_c84ulg_askquestionasync__action_426_askquestionasync_branch_426_4__false -->|next| method_c84ulg_askquestionasync__action_426_askquestionasync_branch_426_4__merge
    method_c84ulg_askquestionasync__action_426_askquestionasync_branch_426_4__merge -->|fallback| method_c84ulg_askquestionasync__action_430_askquestionasync_fallback_430_5__condition
    method_c84ulg_askquestionasync__action_426_askquestionasync_branch_426_4__true -->|next| method_c84ulg_askquestionasync__action_426_askquestionasync_branch_426_4__merge
    method_c84ulg_askquestionasync__action_426_branch_426__condition -->|construct error GroundedResponseDto with first error message| method_c84ulg_askquestionasync__action_426_branch_426__false
    method_c84ulg_askquestionasync__action_426_branch_426__condition -->|assign response from result.Value| method_c84ulg_askquestionasync__action_426_branch_426__true
    method_c84ulg_askquestionasync__action_426_branch_426__false -->|next| method_c84ulg_askquestionasync__action_426_branch_426__merge
    method_c84ulg_askquestionasync__action_426_branch_426__merge -->|next| method_c84ulg_askquestionasync__action_426_askquestionasync_branch_426_4__condition
    method_c84ulg_askquestionasync__action_426_branch_426__true -->|next| method_c84ulg_askquestionasync__action_426_branch_426__merge
    method_c84ulg_askquestionasync__action_430_askquestionasync_fallback_430_5__condition -->|otherwise| method_c84ulg_askquestionasync__action_430_askquestionasync_fallback_430_5__false
    method_c84ulg_askquestionasync__action_430_askquestionasync_fallback_430_5__condition -->|fallback| method_c84ulg_askquestionasync__action_430_askquestionasync_fallback_430_5__true
    method_c84ulg_askquestionasync__action_430_askquestionasync_fallback_430_5__false -->|next| method_c84ulg_askquestionasync__action_430_askquestionasync_fallback_430_5__merge
    method_c84ulg_askquestionasync__action_430_askquestionasync_fallback_430_5__merge -->|next| method_c84ulg_askquestionasync__action_434_askquestionasync_repository_read_434_6__linear
    method_c84ulg_askquestionasync__action_430_askquestionasync_fallback_430_5__true -->|next| method_c84ulg_askquestionasync__action_430_askquestionasync_fallback_430_5__merge
    method_c84ulg_askquestionasync__action_434_askquestionasync_repository_read_434_6__linear -->|exception| method_c84ulg_askquestionasync__action_439_askquestionasync_catch_439_7__catch
    method_c84ulg_askquestionasync__action_439_askquestionasync_catch_439_7__catch -->|next| method_c84ulg_askquestionasync__action_447_askquestionasync_finally_447_8__finally
    method_c84ulg_askquestionasync__action_447_askquestionasync_finally_447_8__finally -->|next| method_c84ulg_askquestionasync__action_447_finally_447__finally
    method_c84ulg_askquestionasync__action_447_finally_447__finally -->|return| method_c84ulg_askquestionasync__implicit_return
    method_c84ulg_askquestionasync__call_425_AskQuestionAsync -->|next| method_c84ulg_askquestionasync__action_426_branch_426__condition
    method_c84ulg_askquestionasync__entry -->|next| method_c84ulg_askquestionasync__action_410_guard_clause_410__condition
```

## Diagram Validation

- Status: warn
- Warning: Control-flow extraction left 1 unresolved jumps.
- Warning: control-flow: diagram method_c84ulg_askquestionasync__fragment_diagram exceeds preferred complexity thresholds (40 nodes, 46 edges).
