feat(assistant): генерация тестов в банк вопросов (фича 5/6)

Учитель: режим «Тест в банк» в Квантике — тема/текст превращается ИИ в вопросы
с выбором ответа, ревью в чате (варианты, верный подсвечен, пояснение),
кнопка «Сохранить в банк» (выбор предмета + тема) создаёт их через POST /questions.

Бэкенд: questionsFromText (по образцу flashcardsFromText, надёжный парс JSON
с починкой обрезанного) + роут POST /assistant/questions (requireRole
teacher/admin, fcLimiter). Клиент: LS.assistantQuestions. Виджет: режим quiz
только для учителя + makeQuiz (рендер и сохранение через createQuestion/getSubjects).

Проверено на живом шлюзе: 5 валидных вопросов, верный индекс в диапазоне.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Maxim Dolgolyov
2026-06-24 15:09:02 +03:00
parent bc0ed1892f
commit 78aea47619
4 changed files with 112 additions and 3 deletions
+2 -1
View File
@@ -1183,7 +1183,7 @@ window.LS = {
customSimsList, customSimGet, customSimCreate, customSimUpdate, customSimDelete,
customSimShare, customSimClone, customSimRelated, customSimAddLink, customSimDelLink,
gameProgressList, gameProgressSubmit,
assistantContext, assistantSeen, assistantDismiss, assistantSettings, assistantAsk, assistantAskStream, assistantFlashcards, assistantFeedback, assistantMemory, assistantMemoryClear, imageGen, imageGenStatus,
assistantContext, assistantSeen, assistantDismiss, assistantSettings, assistantAsk, assistantAskStream, assistantFlashcards, assistantQuestions, assistantFeedback, assistantMemory, assistantMemoryClear, imageGen, imageGenStatus,
adminGetAssistant, adminSaveAssistant, adminTestAssistant, adminReindexTextbooks,
adminSaveProvider, adminDeleteProvider, adminSetActiveProvider, adminAssistantModels,
adminAssistantScan, adminAssistantProbe, adminAssistantApplyModels, adminAssistantHealth,
@@ -1459,6 +1459,7 @@ async function assistantAskStream(q, context, history, mode, cbs) {
if (buf.trim()) handle(buf);
}
async function assistantFlashcards(text, title, count) { return req('POST', '/assistant/flashcards', { text, title, count }); }
async function assistantQuestions(text, count) { return req('POST', '/assistant/questions', { text, count }); }
async function assistantFeedback(rating, q) { return req('POST', '/assistant/feedback', { rating, q: q || undefined }); }
async function assistantMemory() { return req('GET', '/assistant/memory'); }
async function assistantMemoryClear(id) { return req('DELETE', '/assistant/memory' + (id ? '/' + id : '')); }