Skip to content

feat(ai): Tutor Agent web UI — Smart session with visible reasoning (AI-Agent-2)#398

Merged
mrviduus merged 1 commit into
mainfrom
feat/tutor-ui
Jun 24, 2026
Merged

feat(ai): Tutor Agent web UI — Smart session with visible reasoning (AI-Agent-2)#398
mrviduus merged 1 commit into
mainfrom
feat/tutor-ui

Conversation

@mrviduus

Copy link
Copy Markdown
Owner

The web UI for the Tutor agent (frontend slice; backend shipped in #397). Adds backend DTO enrichment so cards render straight from the plan. architect → frontend → adversarial QA → fix cycle.

What

  • "Smart session" entry on the Vocabulary page → TutorSessionPage (/:lang/vocabulary/tutor).
  • Plan view = the showcase: the tutor's overall rationale, each item's word + exercise-type badge + difficulty + per-item why, and the closing readingNudge. Visible reasoning, not debug text.
  • Study phase reuses the existing FlashCard (word → flip → Got it / Missed it; responseTimeMs measured).
  • HITL feedback loop: /feedback re-plans the remainder ("your tutor adjusted your plan") until an empty plan → summary (studied / accuracy / nudge).
  • State machine useTutorSession (planning→plan→study→…→summary + empty / error / signIn).

Backend fix (the blocker QA caught)

The UI used to re-fetch the user's vocab and join by id to render cards — which silently dropped planned cards for users with >100 words (server caps getWords at 100 + a non-existent 'recent' sort that ordered by creation date, not SRS due-ness). Fixed at the source: TutorEndpoints now loads each plan item's card scoped to the caller (Id IN ids AND UserId == userId — a second anti-hallucination/isolation re-check) and enriches TutorPlanItemDto with translation/definition/sentence/bookTitle/hint/distractors. The client renders directly from the plan — no join, nothing dropped. Plus a re-plan turn cap (MaxTurns=6 server + 8-round client backstop) so a persistently-missed card can't loop forever.

UI hardening (adversarial QA)

AbortController/mounted-guard (no setState-after-unmount); feedback-failure retry re-submits the same session (doesn't lose progress); untrusted LLM strings (why/rationale/nudge) line-clamped with an unknown-exerciseType fallback (no raw i18n-key leak).

Verify

tsc clean · 584 web + 35 backend Tutor + AiEvals green · vite build green · browser-checked (entry→plan→study→re-plan→summary, + empty / unknown-type / long-text / unmount-mid-plan, 0 console errors). No migration.

Deferred

Mobile Tutor UI, SSE plan streaming, generated MC exercises beyond the existing card, admin replay link.

🤖 Generated with Claude Code

…AI-Agent-2)

Frontend for the Tutor agent: "Smart session" on the Vocabulary page surfaces
the tutor's plan + per-item why + reading nudge, studies the planned cards via
the existing FlashCard, and re-plans on HITL feedback until done -> summary.
New TutorSessionPage (/:lang/vocabulary/tutor), useTutorSession state machine,
TutorPlanView, tutor.ts client.

Backend (anti-join fix): the UI no longer re-fetches+joins vocab (which dropped
planned cards for >100-word users via the 100-cap + bad sort). TutorEndpoints
loads each plan item's card scoped to the caller (Id IN ids AND UserId==userId —
a 2nd anti-hallucination/isolation re-check) and enriches TutorPlanItemDto with
translation/definition/sentence/bookTitle/hint/distractors. Re-plan turn cap
(MaxTurns=6 server + 8-round client backstop) prevents infinite loops.

UI hardening (adversarial QA): AbortController/mounted-guard, feedback retry
re-submits the SAME session (no progress loss), LLM strings line-clamped +
unknown-exerciseType fallback.

tsc clean; 584 web + 35 backend Tutor + AiEvals green; vite build green;
browser-checked (entry->plan->study->re-plan->summary + edge states, 0 console errors).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@mrviduus mrviduus merged commit b3f07c6 into main Jun 24, 2026
5 checks passed
@mrviduus mrviduus deleted the feat/tutor-ui branch June 24, 2026 23:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant