feat(ai): LangGraph as core runtime + AI Agents/Tools console + full-demo seed
Some checks failed
CI / Frontend — lint + build + e2e (pull_request) Failing after 1m20s
CI / Backend — Odoo HttpCase (pull_request) Failing after 1s

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:
Yamen Ahmad
2026-04-25 03:13:55 +04:00
parent 1223074bde
commit e2aa8031ff
56 changed files with 9846 additions and 40 deletions

View File

@@ -31,6 +31,8 @@ const ar: Translations = {
email: "البريد الإلكتروني",
user: "المستخدم",
home: "الرئيسية",
saving: "جارٍ الحفظ…",
disabled: "معطّل",
},
auth: {
signIn: "تسجيل الدخول",
@@ -50,6 +52,9 @@ const ar: Translations = {
errorTitle: "خطأ",
},
nav: {
smartWizard: "المعالج الذكي",
quickSetup: "الإعداد السريع",
coursePlans: "خطط المقررات (الذكاء الاصطناعي)",
adminDashboard: "لوحة الإدارة",
platformDashboard: "لوحة المنصّة",
dashboard: "لوحة التحكم",
@@ -66,7 +71,7 @@ const ar: Translations = {
rubrics: "معايير التقييم",
generation: "التوليد",
reviewQueue: "قائمة المراجعة",
aiPrompts: "تعليمات الذكاء الاصطناعي",
aiPrompts: "وكلاء الذكاء الاصطناعي والأدوات",
aiFeedback: "ملاحظات الذكاء الاصطناعي",
approvalWorkflows: "سير عمل الموافقات",
taxonomy: "التصنيف",
@@ -337,6 +342,535 @@ const ar: Translations = {
commentRequired: "من فضلك أخبرنا بالخطأ.",
submit: "إرسال الملاحظات",
},
quickSetup: {
adminTitle: "الإعداد السريع",
adminSubtitle:
"كل ما تحتاجه لإطلاق منصّة جاهزة للامتحانات بالترتيب الموصى به. يتم تعليم كل خطوة تلقائياً عند اكتمالها.",
teacherTitle: "الإعداد السريع",
teacherSubtitle: "ابدأ دورة جديدة من البداية إلى النهاية، ثم انتقل إلى المهام اليومية الشائعة.",
progressLabel: "التقدم",
recommendedFlow: "المسار الموصى به",
otherQuickCreates: "إنشاء سريع آخر",
ready: "جاهز",
start: "ابدأ",
review: "مراجعة",
open: "فتح",
helpAria: "عرض المساعدة",
admin: {
step1: {
title: "أنشئ معيار تقييم (Rubric)",
description: "حدّد معايير التقييم لمهام الكتابة والتحدّث. تُستخدم هذه المعايير لاحقاً عند توليد الامتحانات واعتمادها.",
help: "المعيار هو شبكة تقييم (درجات × عناصر). يمكنك البدء من قالب جاهز أو تركيبه من عناصر محدّدة مسبقاً.",
},
step2: {
title: "عرّف بنية الامتحان",
description: "حدّد الأقسام والمهام والأجزاء التي يجب أن يحتويها كل امتحان من هذا النوع سواء مولّداً أو مخصّصاً.",
help: "البنى تضمن الاتساق. مثلاً: بنية IELTS للكتابة تحتوي على المهمة ١ (١٥٠ كلمة) والمهمة ٢ (٢٥٠ كلمة)؛ سيرفض النظام الإرسال إن نقصت إحداهما.",
},
step3: {
title: "ولّد أو أنشئ امتحاناً",
description: "استخدم التوليد بالذكاء الاصطناعي (الأسرع) أو أنشئ امتحاناً مخصّصاً يدوياً. احفظ كمسودة أو أرسله للموافقة.",
help: "التوليد يختار بنية ومعيار تقييم ثم يُنتج الأسئلة. المنشئ المخصّص يتيح لك تحكّماً كاملاً للامتحانات التجريبية.",
},
step4: {
title: "راجع واعتمد",
description: "يعتمد المصدّقون الامتحانات قبل ظهورها للطلاب. اضبط سير العمل مرة واحدة ليتم توجيه الطلبات تلقائياً.",
help: "قائمة الاعتماد تعرض كل امتحان في انتظار المصادقة. الرفض يعيده للمؤلّف، والقبول ينشره.",
},
step5: {
title: "عيّن للطلاب",
description: "جدول الامتحان المنشور، اختر الدفعة، وأرسله. يراه الطلاب فوراً في بوّابتهم.",
help: "يمكن استهداف طلاب أفراد أو دفعات أو صفوف كاملة مع مراعاة المنطقة الزمنية.",
},
quick: {
course: { title: "دورة جديدة", description: "أنشئ هيكل دورة ليملأها المعلّمون بالفصول." },
resource: { title: "رفع مورد", description: "أضف ملفات PDF أو صوت أو فيديو أو روابط إلى المكتبة المشتركة." },
student: { title: "إضافة طالب", description: "أنشئ حساب طالب وعيّنه إلى دفعة." },
teacher: { title: "إضافة معلّم", description: "ادعُ معلّماً وامنحه صلاحيات التدريس." },
classroom: { title: "صف جديد", description: "جمّع الطلاب لأغراض الجدولة والحضور." },
examSession: { title: "جدولة جلسة امتحان", description: "أنشئ جلسة امتحان مراقبة لامتحان مؤسسي." },
customExam: { title: "امتحان مخصّص", description: "أنشئ امتحاناً يدوياً من الصفر بتحكّم كامل." },
ticket: { title: "فتح تذكرة", description: "افتح تذكرة دعم نيابة عن مستخدم." },
},
},
teacher: {
step1: {
title: "أنشئ دورة",
description: "امنح دورتك اسماً، اختر المادّة، وحدّد مستواها. يمكنك تعديل الفصول بعد الإنشاء.",
help: "الدورات هي الحاوية للفصول والمواد والواجبات.",
},
step2: {
title: "أضف الفصول والمحتوى",
description: "افتح دورتك وأضف فصولاً تحتوي على دروس وفيديوهات واختبارات ومهام تدريب.",
help: "الفصول تنظّم أهداف التعلّم. استخدم الورشة الذكية لإنشاء المحتوى تلقائياً.",
},
step3: {
title: "ارفع الموارد",
description: "شارك مع طلابك ملفات PDF أو صوت أو فيديو داعمة عبر المكتبة.",
help: "الملفات الكبيرة مدعومة — يقبل الخادم حتى ١٢٨ ميغابايت للرفعة الواحدة.",
},
step4: {
title: "أنشئ واجباً",
description: "حوّل امتحاناً منشوراً أو مهمّة إلى واجب بتاريخ تسليم ودفعة مستهدفة.",
help: "تظهر الواجبات تلقائياً في لوحة كل طالب وفي جدوله.",
},
step5: {
title: "تابع تقدّم الطلاب",
description: "راقب التسليمات والحضور ورؤى التعلّم التكيّفي لصفّك.",
help: "يحدّد محرك التعلّم التكيّفي الطلاب المعرّضين للخطر لتتدخّل مبكّراً.",
},
quick: {
discussion: { title: "نقاش جديد", description: "ابدأ موضوع نقاش لصفّك." },
announcement: { title: "إعلان جديد", description: "أرسل رسالة لجميع طلابك." },
attendance: { title: "تسجيل الحضور", description: "سجّل حضور اليوم لإحدى الجلسات." },
},
},
},
wizardHub: {
title: "المعالج الذكي",
subtitle:
"اختر أي سيناريو وسيرشدك المعالج خطوة بخطوة. لا حاجة للبحث في الإعدادات — كلّ ضغطة على \"التالي\" تقرّبك أكثر من الإنجاز.",
recommendedOrder: "الترتيب الموصى به",
order: {
rubric: "أنشئ معايير التقييم (الكتابة / المحادثة)",
structure: "حدّد هيكل الامتحان (الأقسام والمهام والمدد)",
generate: "أنشئ امتحاناً تلقائياً أو يدوياً",
approve: "راجع الامتحانات المعلّقة واعتمدها",
assign: "أسند الامتحانات إلى الطلاب",
},
guided: "معالجات موجّهة",
advanced: "الصفحات الكاملة (متقدّم)",
advancedBadge: "متقدّم",
aiBadge: "ذكاء اصطناعي",
startWizard: "ابدأ المعالج",
openPage: "افتح الصفحة",
cards: {
rubric: {
title: "إنشاء معيار تقييم",
description: "الاسم ← المهارة ← المعايير ← الوصف ← المراجعة. للكتابة والمحادثة فقط.",
},
examStructure: {
title: "تعريف هيكل امتحان",
description: "الاسم ← الوحدات ← مهام الكتابة ← المراجعة. قالب قابل لإعادة الاستخدام.",
},
course: {
title: "إنشاء مساق",
description: "العنوان ← المستوى والسعة ← المراجعة. الفصول تُضاف من صفحة المساق.",
},
coursePlan: {
title: "توليد خطة مقرر (ذكاء اصطناعي)",
description: "اوصف المقرر فيكتب الذكاء الاصطناعي الأهداف ونتائج التعلّم لكل مهارة ونطاق القواعد وخطة التسليم أسبوعياً، ثم يولّد المواد التعليمية الجاهزة لكل أسبوع.",
},
generation: {
title: "توليد امتحان",
description: "صفحة التوليد الكاملة بخيارات المعايير والهيكل وتحكّم في كل وحدة.",
},
approval: {
title: "مسارات الموافقة",
description: "حدّد من يراجع الامتحانات، وتابع الطلبات المعلّقة.",
},
assign: {
title: "إسناد إلى الطلاب",
description: "صفحة الجدولة الكاملة مع منتقي الطلاب والنوافذ الزمنية والمنطقة الزمنية.",
},
resource: {
title: "رفع مورد",
description: "أضف ملفات PDF أو صوت أو فيديو أو روابط إلى المكتبة.",
},
student: {
title: "إضافة طالب",
description: "أنشئ حساب طالب وسجّله في دفعة.",
},
},
},
wizard: {
back: "السابق",
next: "التالي",
finish: "إنهاء",
backToHub: "العودة إلى المعالجات",
stepOf: "الخطوة {{current}} من {{total}}",
rubric: {
title: "إنشاء معيار تقييم",
subtitle: "شبكة تقييم لمهام الكتابة أو المحادثة، يُرجَع إليها عند توليد الامتحانات أو اعتمادها.",
finish: "إنشاء المعيار",
toastSuccess: "تم إنشاء المعيار",
toastError: "تعذّر إنشاء المعيار",
addCriterion: "إضافة معيار",
removeCriterion: "حذف المعيار",
unnamedCriterion: "(معيار بلا اسم)",
descriptorHint: "الوصف اختياري. يظهر للمصحّحين كإرشاد لكل معيار.",
maxLabel: "الحد الأقصى",
moduleHint: "تنطبق المعايير على الكتابة والمحادثة فقط. الاستماع والقراءة يُصحَّحان تلقائياً.",
step1: {
title: "الأساسيات",
description: "امنح المعيار اسماً وحدّد المهارة التي يطبّق عليها.",
},
step2: {
title: "المعايير",
description: "أضف المعايير التي سيقوم المصحّحون بتقييمها. لكل معيار حد أقصى (مثل 9 لامتحان IELTS).",
},
step3: {
title: "الأوصاف",
description: "اختياري: صف ما يقيسه كل معيار. يراها المصحّحون كتلميحات.",
},
step4: {
title: "المراجعة",
description: "راجع وأنشئ.",
},
labels: {
name: "اسم المعيار",
module: "المهارة",
description: "الوصف",
criterionName: "اسم المعيار الفرعي",
maxScore: "الحد الأقصى",
},
placeholders: {
name: "مثال: IELTS مهمة كتابة 2",
description: "وصف قصير يظهر للمصحّحين.",
criterionName: "مثال: الاستجابة للمهمة",
descriptor: "ماذا يجب على المصحّح أن يتحقق منه لهذا المعيار.",
},
modules: {
writing: "الكتابة",
speaking: "المحادثة",
},
errors: {
nameRequired: "يرجى إدخال اسم للمعيار.",
moduleRestricted: "المعايير تنطبق على الكتابة أو المحادثة فقط.",
criterionRequired: "أضف معياراً واحداً على الأقل.",
criterionName: "كل معيار يحتاج إلى اسم.",
criterionScore: "الحد الأقصى يجب أن يكون بين 1 و 100.",
},
},
structure: {
title: "تعريف هيكل امتحان",
subtitle: "قالب يحدّد الأقسام والمهام التي يجب أن يحتويها كل امتحان من هذا النوع.",
finish: "إنشاء الهيكل",
toastSuccess: "تم إنشاء هيكل الامتحان",
toastError: "تعذّر إنشاء هيكل الامتحان",
industryHint: "اختياري: مثل \"الإنجليزية التجارية\"، \"الرعاية الصحية\".",
writingSkipped: "الكتابة غير مُحدَّدة ضمن الوحدات — تم تخطّي هذه الخطوة.",
wordsSuffix: "كلمة",
addTask: "إضافة مهمة",
removeTask: "حذف المهمة",
step1: {
title: "الأساسيات",
description: "سمِّ الهيكل وحدّد نوع الامتحان.",
},
step2: {
title: "الوحدات",
description: "اختر الوحدات التي يغطّيها هذا الهيكل. سيراها الطلاب كأقسام.",
},
step3: {
title: "مهام الكتابة",
description: "للكتابة، حدّد الحد الأدنى لعدد الكلمات لكل مهمة.",
},
step4: {
title: "المراجعة",
description: "راجع وأنشئ.",
},
labels: {
name: "اسم الهيكل",
industry: "المجال / السياق",
examType: "نوع الامتحان",
modules: "الوحدات",
taskLabel: "اسم المهمة",
minWords: "أدنى كلمات",
},
placeholders: {
name: "مثال: IELTS أكاديمي كتابة",
industry: "مثال: الإنجليزية التجارية",
},
examTypes: {
academic: "أكاديمي",
general: "عام",
},
modules: {
listening: {
title: "الاستماع",
description: "أسئلة مبنيّة على الصوت (تصحيح تلقائي).",
},
reading: {
title: "القراءة",
description: "أسئلة مبنيّة على مقاطع (تصحيح تلقائي).",
},
writing: {
title: "الكتابة",
description: "مهام مقاليّة تُصحَّح باستخدام معيار تقييم.",
},
speaking: {
title: "المحادثة",
description: "مهام شفهيّة تُصحَّح باستخدام معيار تقييم.",
},
},
errors: {
nameRequired: "يرجى إدخال اسم للهيكل.",
moduleRequired: "اختر وحدة واحدة على الأقل.",
writingTaskRequired: "الكتابة تحتاج إلى مهمة واحدة على الأقل.",
writingTaskLabel: "كل مهمة كتابة تحتاج إلى اسم.",
writingTaskWords: "الحد الأدنى للكلمات يجب أن يكون 1 على الأقل.",
},
},
course: {
title: "إنشاء مساق",
subtitle: "هيكل مساق خفيف. يمكنك إضافة الفصول والمواد وتسجيل الطلاب بعد الإنشاء.",
finish: "إنشاء المساق",
toastSuccess: "تم إنشاء المساق",
toastError: "تعذّر إنشاء المساق",
codeHint: "اتركه فارغاً لتوليده تلقائياً من العنوان.",
difficultyHint: "ما مدى تحدّي هذا المساق إجمالاً؟ يُستخدم للبحث والتصفية.",
cefrHint: "إن كان المساق يستهدف مستوى CEFR محدداً، اختره هنا.",
step1: {
title: "الأساسيات",
description: "امنح المساق اسماً ووصفاً قصيراً.",
},
step2: {
title: "المستوى والسعة",
description: "حدّد الصعوبة ومستوى CEFR المستهدف والحد الأقصى لعدد الطلاب.",
},
step3: {
title: "المراجعة",
description: "راجع وأنشئ.",
},
labels: {
title: "عنوان المساق",
code: "رمز المساق",
description: "الوصف",
difficulty: "الصعوبة",
cefrLevel: "مستوى CEFR",
capacity: "السعة القصوى",
},
placeholders: {
title: "مثال: إنجليزية تأسيسية المستوى 1",
code: "سيتم توليده تلقائياً إذا تُرك فارغاً",
description: "لمن هذا المساق؟ ماذا سيتعلّمون؟",
difficulty: "اختر مستوى صعوبة",
cefr: "اختر مستوى CEFR",
},
difficulty: {
beginner: "مبتدئ",
intermediate: "متوسط",
advanced: "متقدّم",
},
errors: {
titleRequired: "يرجى إدخال عنوان المساق.",
capacityRequired: "السعة القصوى يجب أن تكون 1 على الأقل.",
},
},
},
coursePlan: {
listTitle: "خطط المقررات",
listSubtitle:
"خطط مناهج يُنشئها الذكاء الاصطناعي: الأهداف، ونتائج التعلّم لكل مهارة، ونطاق القواعد، وخطة التسليم أسبوعياً، مع توليد المواد التعليمية لكل أسبوع عند الطلب.",
generateNew: "توليد خطة جديدة",
searchPlaceholder: "ابحث عن خطة بالاسم…",
loadFailed: "تعذّر تحميل الخطط.",
deleted: "تم حذف الخطة.",
deleteFailed: "تعذّر حذف الخطة.",
delete: "حذف",
confirmDelete: "حذف الخطة \"{{name}}\"؟ سيؤدي ذلك إلى إزالة جميع الأسابيع والمواد.",
emptyTitle: "لا توجد خطط بعد",
emptySubtitle: "استخدم معالج الذكاء الاصطناعي لتوليد أول خطة — يستغرق الأمر نحو دقيقة.",
open: "فتح",
backToList: "العودة إلى الخطط",
noDescription: "لا يوجد وصف.",
weeksCount_one: "{{count}} أسبوع",
weeksCount_other: "{{count}} أسابيع",
materialsCount_one: "{{count}} مادة",
materialsCount_other: "{{count}} مواد",
hoursPerWeek: "{{count}} ساعة/أسبوع",
weekN: "الأسبوع {{n}}",
generateMaterials: "توليد مواد الأسبوع (ذكاء اصطناعي)",
regenerateMaterials: "إعادة توليد مواد الأسبوع",
generating: "جاري التوليد…",
generateHint:
"سيُنتج الذكاء الاصطناعي نصّ قراءة وسيناريو استماع ومحفّزات محادثة وسؤال كتابة ودرس قواعد وقائمة مفردات لهذا الأسبوع.",
weekMaterialsGenerated: "تم توليد مواد الأسبوع.",
weekMaterialsFailed: "تعذّر توليد مواد الأسبوع.",
generateSuccess: "تم توليد خطة المقرر.",
generateFailed: "تعذّر توليد خطة المقرر.",
deliveryHint: "افتح أي أسبوع لعرض النتائج المخطَّطة وتوليد المواد الجاهزة للاستخدام.",
status: {
draft: "مسودة",
generated: "مُولّدة",
approved: "معتمدة",
archived: "مؤرشفة",
},
sections: {
objectives: "أهداف المقرر",
outcomes: "نتائج التعلّم حسب المهارة",
grammar: "نطاق القواعد",
assessment: "التقييم",
resources: "المصادر",
delivery: "خطة التسليم الأسبوعية",
},
skill: {
reading: "القراءة",
writing: "الكتابة",
listening: "الاستماع",
speaking: "المحادثة",
grammar: "القواعد",
vocabulary: "المفردات",
integrated: "متكامل",
},
materialType: {
reading_text: "نص قراءة",
listening_script: "نص استماع",
speaking_prompt: "محفّز محادثة",
writing_prompt: "مهمّة كتابة",
grammar_lesson: "درس قواعد",
vocabulary_list: "قائمة مفردات",
practice: "تمرين",
other: "مادة",
},
table: {
skill: "المهارة",
outcomes: "النتائج",
remarks: "ملاحظات",
},
wizard: {
title: "توليد خطة مقرر",
subtitle:
"اوصف المقرر مرّة واحدة، ويكتب الذكاء الاصطناعي الخطة كاملة — الأهداف والنتائج والقواعد والخطة الأسبوعية — ويمكنك توليد مواد الأسبوع الأول بضغطة واحدة.",
finish: "توليد الخطة",
reviewHint: "اضغط على \"توليد الخطة\" لبدء الذكاء الاصطناعي. يستغرق عادةً 3060 ثانية، وستنتقل إلى صفحة الخطة عند الانتهاء.",
steps: {
basics: "الأساسيات",
basicsDesc: "سمِّ المقرر وحدّد المستوى والمدة وعدد الساعات الأسبوعية.",
coverage: "التغطية",
coverageDesc: "أخبر الذكاء الاصطناعي بتوزيع الساعات على المهارات ومن هم المتعلّمون.",
scope: "النطاق",
scopeDesc: "اختياري: تركيز القواعد، والمصادر، وملاحظات حرّة.",
review: "المراجعة",
reviewDesc: "راجع البيانات قبل بدء التوليد.",
},
fields: {
title: "عنوان المقرر",
cefr: "مستوى CEFR",
cefrPlaceholder: "اختر مستوى",
totalWeeks: "إجمالي الأسابيع",
contactHours: "عدد الساعات أسبوعياً",
skillsDivision: "توزيع المهارات",
skillsDivisionHint:
"صيغة حرّة — مثال: \"10 س/أسبوع قراءة وكتابة + 8 س/أسبوع استماع ومحادثة\". اتركه فارغاً ليقرّر الذكاء الاصطناعي.",
learnerProfile: "ملف المتعلّمين",
learnerProfilePlaceholder: "من هم المتعلّمون؟ الفئة العمرية، اللغة الأم، الخلفية الدراسية، الأهداف…",
grammarFocus: "تركيز القواعد (Enter للإضافة)",
grammarFocusPlaceholder: "مثال: المضارع البسيط",
resources: "المصادر (Enter للإضافة)",
resourcesPlaceholder: "مثال: Pathways 1 (National Geographic)",
notes: "ملاحظات إضافية",
notesPlaceholder: "أي شيء آخر يحتاج الذكاء الاصطناعي معرفته.",
},
errors: {
titleRequired: "يرجى إدخال عنوان المقرر.",
cefrRequired: "يرجى اختيار مستوى CEFR.",
weeksRange: "عدد الأسابيع يجب أن يكون 1 على الأقل.",
},
},
},
aiAdmin: {
title: "وكلاء الذكاء الاصطناعي والأدوات",
subtitle:
"هيّئ الوكلاء المبنيين على LangGraph الذين يشغّلون تخطيط المقررات وتوليد الاختبارات والتمارين والمدرّس داخل LMS والتصحيح. الإعدادات الافتراضية جاهزة للاستخدام مباشرة.",
tabs: {
agents: "الوكلاء",
tools: "الأدوات",
prompts: "التعليمات",
},
},
agents: {
list: {
title: "الوكلاء",
subtitle: "مهيّأون مسبقاً لكل ركيزة في المنصة — يمكن تعديل الإعدادات الافتراضية أدناه.",
search: "ابحث عن وكيل…",
empty: "لا توجد وكلاء مطابقون لبحثك.",
},
detail: {
configure: "ضبط الإعدادات",
empty: "اختر وكيلاً لعرض إعداداته.",
graph: "نوع الرسم البياني",
model: "النموذج",
temperature: "درجة الإبداع",
tokens: "أقصى عدد رموز",
format: "صيغة المخرجات",
fallback: "الاحتياطي",
revisions: "أقصى عدد مراجعات",
promptKey: "مفتاح القالب",
toolsTitle: "الأدوات المفعّلة",
noTools: "لا توجد أدوات مفعّلة لهذا الوكيل.",
systemPrompt: "تعليمات النظام",
noPrompt: "(فارغ)",
},
config: {
title: "ضبط الإعدادات",
saved: "تم حفظ إعدادات الوكيل",
name: "اسم العرض",
promptKey: "مفتاح القالب (مع نسخ)",
description: "الوصف",
systemPrompt: "تعليمات النظام",
systemPromptHint:
"إذا تم تعيين مفتاح قالب أعلاه، فإن النسخة النشطة من ذلك القالب تستبدل هذا الحقل وقت التشغيل.",
model: "النموذج",
fallbackModel: "النموذج الاحتياطي",
responseFormat: "صيغة المخرجات",
text: "نص",
temperature: "درجة الإبداع",
maxTokens: "أقصى عدد رموز",
maxRevisions: "أقصى عدد مراجعات",
graphType: "بنية الرسم البياني",
qualityChecks: "فحوصات الجودة (مفاتيح أدوات مفصولة بفواصل)",
tools: "الأدوات المفعّلة",
mutates: "كتابة",
active: "الوكيل مفعّل",
},
test: {
title: "محرّك الاختبار",
subtitle:
"أرسل طلباً صغيراً وافحص مخرجات الوكيل واستدعاءات الأدوات وتنبيهات الجودة.",
variables: "المتغيّرات (JSON)",
payload: "الطلب (نص أو JSON)",
payloadPlaceholder:
"ماذا يجب أن يفعل الوكيل؟ مثال: «أنشئ 5 أسئلة اختيار من متعدد للقراءة لمستوى B1.»",
run: "تشغيل الوكيل",
running: "جارٍ التشغيل…",
ok: "تم تنفيذ الوكيل بنجاح",
output: "المخرجات",
toolTrace: "سجلّ استدعاءات الأدوات",
iterations: "التكرارات",
revisions: "المراجعات",
toolCalls: "استدعاءات الأدوات",
retrievalHits: "نتائج الاسترجاع",
qualityIssues: "تنبيهات الجودة",
badVarsJson: "يجب أن تكون المتغيّرات بصيغة JSON صحيحة.",
},
graph: {
simple: "بسيط",
planReviewRevise: "تخطيط • مراجعة • تنقيح",
rag: "استرجاع وتوليد",
react: "ReAct (استدعاء أدوات)",
},
},
tools: {
title: "أدوات الوكلاء",
subtitle:
"القدرات التي يمكن للوكلاء استدعاؤها. أوقف أداة لإخراجها من جميع الوكلاء دون تعديل كل واحد منهم.",
search: "ابحث عن أداة…",
empty: "لا توجد أدوات مطابقة لبحثك.",
writes: "كتابة",
toggle: {
enabled: "تم تفعيل الأداة",
disabled: "تم تعطيل الأداة",
},
col: {
key: "المفتاح",
name: "الاسم",
category: "الفئة",
description: "الوصف",
params: "المعاملات",
active: "نشط",
},
},
};
export default ar;