feat(ai): LangGraph as core runtime + AI Agents/Tools console + full-demo seed
Core AI runtime - New encoach.ai.agent + encoach.ai.tool models with M2M tool binding, graph topology (simple|plan_review_revise|rag|react), model + fallback, temperature, max_tokens, response_format, max_revisions, quality checks and system prompt fields. - services/agent_runtime.py compiles a langgraph.StateGraph per agent and caches the build per (key, write_date). Emits a structured trace (output, tool_calls, retrieval_hits, revisions, quality_issues, ms, model_used, fallback_used) and auto-falls-back on rate-limit/5xx. - services/agent_tools.py registers 11 tool handlers wrapping existing services: resources.search, rubric.fetch, outcomes.fetch, student.profile, quality.cefr_check, quality.ai_detect, quality.content_gate, course_plan.save (mutates), course_plan.save_materials (mutates), scoring.grade_writing, scoring.grade_speaking. - 7 default agents seeded via data/agents_defaults.xml: course_planner, course_week_materials, exam_generator, exercise_generator, lms_tutor, writing_grader, speaking_grader. - Feature flag encoach_ai.use_langgraph_runtime (default True). - encoach_ai_course pipeline now routes through AgentRuntime when on, legacy SDK path kept as fallback. Admin UI - /admin/ai/prompts is now a tabbed Agents | Tools | Prompts console. - AIAgentsPanel: card grid + config dialog (model/temp/graph/tools/ system prompt) + built-in Test Runner showing live trace. - AIToolsPanel: registry table with category badges, mutates flag, schema viewer, edit dialog. - New /api/ai/agents* and /api/ai/tools* controller (list/get/update/ test, list-tools, toggle-tool). - Sidebar label nav.aiPrompts -> nav.aiAgents (AI Agents and Tools). - EN + AR (RTL) translations for ~80 new keys. Smart Wizard pages - /admin/quick-setup hub + CourseWizard, CoursePlanWizard, RubricWizard, ExamStructureWizard step-by-step flows. - /admin/course-plans list + detail pages. - /teacher/quick-setup mirror. Full demo seed + 8-role E2E - seed_full_demo.py adds the 5 missing user_types (approver, corporate, mastercorporate, agent, developer), activates a 2-stage exam-approval workflow with one pending request, creates a GE1-aligned 12-week B1 course plan with 6 detailed Week-1 materials (reading 400w, writing, listening 4-min script, speaking, grammar present simple vs continuous, vocabulary), and inserts sample ai.log + ai.feedback rows. - reset_demo_passwords.py forces every demo login back to canonical passwords (admin123/teacher123/student123/approver123/corporate123/ master123/agent123/dev123). - e2e_full_scenario.py: 46/46 PASS read-only API smoke across all 8 roles, including a live LangGraph round-trip on writing_grader. - e2e_approval_chain.py: 6/6 PASS mutation E2E - approver approves stage 1, admin approves stage 2, linked encoach.exam.custom flips to status=published, verified via psql. Docs - docs/PROJECT_SUMMARY.md updated to 2026-04-25: new Latest events bullets, refreshed credentials table, full sections 22 (LangGraph runtime) and 23 (full demo seed + 8-role E2E). - docs/ENCOACH_FULL_DEMO_QA_REPORT.md added with credentials, per-endpoint PASS/FAIL, mutation chain proof, LangGraph live output. - backend/GE1 Course Outline_ Fall AY25-26.pdf vendored as the reference outline the GE1 plan/materials are aligned to. Dependencies - requirements.txt: langgraph>=0.2.0, langchain-core>=0.3.0. - encoach_ai/__manifest__.py: external_dependencies updated. Made-with: Cursor
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
import { Outlet, Link, useNavigate, useLocation } from "react-router-dom";
|
||||
import { Suspense } from "react";
|
||||
import { SidebarProvider, SidebarTrigger } from "@/components/ui/sidebar";
|
||||
import {
|
||||
Sidebar, SidebarContent, SidebarGroup, SidebarGroupContent,
|
||||
@@ -31,7 +32,7 @@ import {
|
||||
CalendarDays, Landmark, UserPlus, ScrollText, Award,
|
||||
HelpCircle as FaqIcon, Bell, Workflow,
|
||||
CalendarOff, DollarSign, BookMarked, BarChartHorizontal, TrendingUp,
|
||||
Library, Activity, Warehouse, UserCog, Sparkles,
|
||||
Library, Activity, Warehouse, UserCog, Sparkles, Compass,
|
||||
} from "lucide-react";
|
||||
import React from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
@@ -43,6 +44,7 @@ import { useTranslation } from "react-i18next";
|
||||
interface NavItem { titleKey: string; url: string; icon: LucideIcon }
|
||||
|
||||
const overviewItems: NavItem[] = [
|
||||
{ titleKey: "nav.smartWizard", url: "/admin/smart-wizard", icon: Sparkles },
|
||||
{ titleKey: "nav.adminDashboard", url: "/admin/dashboard", icon: LayoutDashboard },
|
||||
{ titleKey: "nav.platformDashboard", url: "/admin/platform", icon: BarChart3 },
|
||||
];
|
||||
@@ -65,6 +67,7 @@ const academicItems: NavItem[] = [
|
||||
{ titleKey: "nav.reviewQueue", url: "/admin/exam/review-queue", icon: Sparkles },
|
||||
{ titleKey: "nav.aiPrompts", url: "/admin/ai/prompts", icon: Wand2 },
|
||||
{ titleKey: "nav.aiFeedback", url: "/admin/ai/feedback", icon: Sparkles },
|
||||
{ titleKey: "nav.coursePlans", url: "/admin/course-plans", icon: Compass },
|
||||
{ titleKey: "nav.approvalWorkflows", url: "/admin/approval-workflows", icon: GitBranch },
|
||||
];
|
||||
|
||||
@@ -219,6 +222,20 @@ function AppBreadcrumbs() {
|
||||
);
|
||||
}
|
||||
|
||||
// ============= Route content fallback =============
|
||||
// Shown only inside the main content area while a lazy-loaded route chunk
|
||||
// is fetching. Keeping the fallback local means the sidebar and header
|
||||
// stay mounted during navigation — previously the page felt like a full
|
||||
// browser reload because the outer App-level Suspense replaced everything
|
||||
// with a full-viewport spinner.
|
||||
function RouteContentFallback() {
|
||||
return (
|
||||
<div className="flex items-center justify-center py-20">
|
||||
<div className="animate-spin rounded-full h-6 w-6 border-b-2 border-primary" />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
// ============= Main Layout =============
|
||||
export default function AdminLmsLayout() {
|
||||
const { user, logout } = useAuth();
|
||||
@@ -279,7 +296,9 @@ export default function AdminLmsLayout() {
|
||||
</div>
|
||||
</header>
|
||||
<main className="flex-1 overflow-auto p-6">
|
||||
<Outlet />
|
||||
<Suspense fallback={<RouteContentFallback />}>
|
||||
<Outlet />
|
||||
</Suspense>
|
||||
</main>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user