Копия пользовательской автопамяти (29 фактов + индекс MEMORY.md) в .claude/memory/, чтобы переносить между машинами через git. README.md — как восстановить в пользовательскую папку на другой машине. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
16 KiB
name, description, metadata
| name | description | metadata | ||||||
|---|---|---|---|---|---|---|---|---|
| project_pet_assistant | «Квантик-ассистент» — сквозной помощник поверх питомца; Ф0/Ф1/«Спроси» РЕАЛИЗОВАНЫ на master (правиловый движок) |
|
Дизайн-доку: plans/pet-assistant/PLAN.md. Реализация: commit 3f8009c (2026-06-04), на master.
Суть: питомец «Квантик» стал плавающим помощником (низ-слева) на всех страницах — контекстные
подсказки, проактивные напоминания, поздравления, панель «Спроси Квантика». Движок правиловый
(без LLM), правила инлайн в frontend/js/assistant.js.
Фича-гейт: отдельный assistant (commit e1cde83 — сменили с reuse 'pet'), requireFeature('assistant'),
дефолт ON; админ включает/выключает в Управление→фичи (adminController allowed + games.js GAME_FEATURES,
key 'assistant'). Включён всем (assistant_enabled DEFAULT 1 — личный тумблер в профиле);
«видел» — серверная таблица assistant_seen (cross-device); ассистент и на учебнике (через
DEEPLINK_INJECT в server.js); тон консервативный (дневной лимит 2, кулдауны, «не показывать»);
«Спроси» — поиск по FAQ + точка расширения под локальную модель (в ask() контроллера).
Файлы: миграция 062_assistant.sql (assistant_enabled + assistant_seen); assistantController.js
(FAQ инлайн — backend/src/data/ в .gitignore!) + routes/assistant.js; mount /api/assistant
под requireFeature('pet'); js/api.js (assistantContext/Seen/Dismiss/Settings/Ask); загрузчик в
js/sidebar.js (как flashcard-fab); тумблер в profile.html («Настройки» → prefAssistant).
Эндпоинты: GET /context, POST /seen, /dismiss, /ask, PATCH /settings. Лицо — pet-sprite.js,
данные — /api/pet + /api/assistant/context (dueCards, homework).
Сделано: Ф0 (каркас+контекстные подсказки) + Ф1 (проактив: домашка/карточки/серия/квест/
activeLesson «продолжи урок» + поздравления левелап/серия) + Ф2 (коачмарк-тур новичка по разделам,
офер на дашборде, повтор Assistant.tour()) + Ф3-lite (FAQ-«Спроси»). Тур-правило id 'onboarding'
в assistant_seen. activeLesson (commit 9baaca7) — запрос как «продолжить чтение» из courseController.
- Контент-апгрейд (commit
c33295e): контекстные подсказки на ВСЕ разделы (PAGE_HINTS), «Совет дня» (tip-daily, дашборд), FAQ ~10→~50, «Спроси» ищет и по платформе (LS.globalSearch), умный проактив weakSubject (слабый предмет по test_sessions, в /api/assistant/context) + daily-plan (из квестов+карточек). LLM подключена (commit9dbc044): ask() вызывает OpenAI-совместимую модель с грунтовкой по топ-FAQ, source:'model', таймаут 12с, откат на FAQ при ошибке/без ключа. Конфиг ENV в backend/.env(.example): ASSISTANT_LLM_URL (дефолт Groq chat/completions), ASSISTANT_LLM_KEY (пусто → FAQ), ASSISTANT_LLM_MODEL (дефолт llama-3.3-70b-versatile); локальный Ollama без ключа поддержан (localhost → зовётся без Bearer). АКТИВНО (2026-06-04): подключён Google Gemini через OpenAI-совместимый эндпоинт (ASSISTANT_LLM_URL=https://generativelanguage.googleapis.com/v1beta/openai/chat/completions), рабочая модель gemini-2.5-flash (ключ в backend/.env, не в гите). Гочи по моделям на этом ключе: gemini-2.0-flash / -lite → 429 limit:0 (нет free-квоты); gemini-1.5-* → 404; gemini-2.5-flash / gemini-flash-latest → 200. Ключ валиден (auth ок). Сменить провайдера/модель — только через backend/.env + рестарт. Возможности-апгрейд (commit479c621): ответы модели рендерятся markdown + KaTeX (ленивая загрузка katex с jsdelivr; модель просим LaTeX...); ask принимает context; «Объяснить выделенное» (запоминаем selection на mouseup) и «Объяснить/Конспект параграфа» на учебнике (getPageContext по .sec.active); «Флешкарты из параграфа» → POST /api/assistant/flashcards (модель→JSON, есть починка обрезанного, max_tokens 1400) → колода через LS.fcCreateDeck/fcAddCard; репетитор на экзамене — кнопка «Спросить Квантика» в task-card.js (tc-ask) → Assistant.ask(условие+ответ+решение). Экспорт Assistant.ask(q,context) и explainSelection(). Гочи: на этом Gemini-ключе free-квота есть только у gemini-2.5-flash; placeholder в renderRich — @@M..@@ (не цифры-в-пробелах, иначе коллизии). Админ-панель + чат (commitdc073e2): конфиг LLM теперь в app_settings (assistant_llm_url/key/model), правится из Управление→игры (карточка «Помощник Квантик — модель»: пресеты Gemini/Groq/OpenRouter/Ollama, URL/модель/ключ, Сохранить/Проверить/Очистить, статус). Эндпоинты GET/PUT/POST /api/admin/assistant(/test) admin-only. llmConfig() читает app_settings→ENV→дефолт; нет ключа → FAQ-режим. Текущий Gemini-ключ пока в backend/.env (DB пусто → берётся ENV; можно перенести в БД через админку). «Спроси» — многоходовой чат (history последние 6 реплик уходят модели, лента сообщений, «Очистить»). RAG+кэш+учитель (commit2252bbd, миграция 063): RAG — индексатор backend/scripts/index-textbooks.js → таблица textbook_chunks; ask() подмешивает релевантные куски (LIKE-скоринг, ≥2 слова). ГОЧА: бол-во учебников рендерят текст ЧЕРЕЗ JS-движки → в статическом HTML только заголовки §, поэтому индекс берёт только статично-текстовые (≈132 чанка: chemistry, часть physics); JS-рендеримые покрываются контекстом страницы (getPageContext читает отрендеренный DOM). Полное покрытие = headless-рендер — СДЕЛАНО (commit0119ea0): scripts/index-textbooks-headless.js (puppeteer-core + системный Chrome, служебный JWT в localStorage т.к. /textbook требует логина) рендерит учебники через локальный сервер, кликает §, забирает рендерный текст движков. Прогон: 87/107 книг, индекс 132→746 чанков (physics-9 и др. JS-учебники теперь покрыты). npm: index:textbooks:full. Сервер не требует рестарта — ragContext читает БД на каждом запросе.
Батч 4 фич (commit 4224a22, миграция 064): Источники — ragContext отдаёт sources (slug/section/section_ref),
под ответом ссылка «по учебнику X, §N» на /textbook/slug#sec-; section_ref заполняет headless-индексатор
(psel-card data-id); статический индексатор больше НЕ делает delAll (per-book — не затирает headless).
Режим-наставник: ask(mode: answer/hint/check) + промпт; в «Спроси» переключатель из 3 кнопок; на карточке
экзамена (task-card.js) кнопка «Подсказка» (mode hint) рядом со «Спросить Квантика»; Assistant.ask(q,ctx,{mode}).
Оценка: лайк/дизлайк под ответом (assistant_feedback, POST /assistant/feedback) + сводка в админке (up/down/recent).
Утренний бриф: rule 'brief' на дашборде до 12:00 (PET.weeklyXP «N из 5 дн» + план), daily-plan сдвинут на день.
НЕ сделано: цели недели (явная установка) + напоминания по расписанию (нужен планировщик/push); голосовой ввод/TTS;
генератор заданий учителю; авто-cron на index:textbooks:full.
Мета-фильтр + тумблер экзамена (commit 961504b): вопросы про модель/нейросеть/провайдера/системный промпт
отбиваются шаблоном META_RE (саморефренция ты/тебя/твой РЯДОМ с термином модель/gpt/промпт — не блокирует
«модель атома/газа») + запрет в системном промпте. Кнопки «Подсказка»/«Спросить Квантика» на карточках
экзамена по умолчанию СКРЫТЫ (assistant_exam_buttons='0'); тумблер в админке → /context examButtons →
assistant.js вешает html.asst-exam-on (CSS показывает .tc-asst-btn). Память чата: последние 6 реплик уходят
модели, живёт в памяти вкладки до «Очистить»/reload. §-ссылки источников: section_ref у 531/746 чанков (после
headless-reindex); у остальных ссылка ведёт на главу.
Лимит-UX + отдельный раздел админки (commit 7830084): «не помнит» оказалось free-лимитом Gemini (HTTP 429,
≈20 req/min). callLLM теперь возвращает {text,error}; ask отдаёт source:'limit' («много запросов, подожди,
память не потеряется») или 'error'; фронт показывает это и НЕ ломает историю (pop неудачного вопроса). Многоходовость
работала и раньше — глушил лимит. В окне «Спроси» добавлено пояснение про память (≈6 реплик = рабочая память) +
аватар Квантика в шапке, окно шире/мягче. Управление вынесено в отдельный раздел админки «Помощник Квантик»
(frontend/js/admin/sections/assistant.js; AdminSections.assistant; ROUTE_TO_SECTION+ADMIN_ONLY_TABS+btn-tab-assistant;
из games.js конфиг и фича-запись удалены) — там системный вкл/выкл (feature 'assistant' через /api/admin/features) +
модель/ключ/тест/RAG/кнопки экзамена/счётчик/качество. ВАЖНО: free-квота Gemini gemini-2.5-flash = 20 запросов В СУТКИ (quotaId GenerateRequestsPerDayPerProjectPerModel-FreeTier),
остальные модели Gemini на ключе — limit:0. Это мизер → постоянный 429. Решение: сменить провайдера на Groq
(free-тариф щедрый, ~тысячи/день, 30 RPM) — создать ключ console.groq.com, в админ-разделе «Помощник Квантик»
выбрать пресет Groq + вставить ключ; ИЛИ включить billing Gemini; ИЛИ локальная Ollama. Провайдер меняется в админке.
Мульти-провайдер (commit e2bff24): конфиг = список провайдеров app_settings.assistant_providers (JSON
[{id,name,url,model,key}]) + assistant_active. llmConfig=активный; providersOrdered=активный первым + остальные
с ключом; callLLMFailover перебирает их при 429/timeout/network/http (askModel и flashcards идут через него) —
второй ключ авто-подхватывает при исчерпании квоты первого. Legacy assistant_llm_* мигрируются в список при
первом GET админки. Админ-раздел «Помощник Квантик»: список провайдеров (радио=активный, Тест/Изменить/Удалить
по каждому) + форма с пресетами. Эндпоинты POST/DELETE /admin/assistant/provider(/:id), POST /admin/assistant/active.
Решение лимита Gemini (20/сутки): добавить Groq вторым провайдером — failover сам переключит.
ГОЧА: Groq гео-заблокирован в Беларуси («Access denied» на console.groq.com) — ключ не создать без VPN.
Железо машины подходит для ЛОКАЛЬНОЙ модели: 32 ГБ ОЗУ, GTX 1080 8 ГБ VRAM (WMI врёт 4 ГБ) → Qwen2.5-7B через
Ollama идеально. Выбор «локально vs Gemini billing vs OpenRouter» пока НЕ сделан (вопрос прерван). Failover-
уведомление (commit aac1240): callLLMFailover пишет app_settings.assistant_failover {failedName,servedName,reason,at};
при успехе активного снимается; админ-раздел показывает баннер «провайдер X недоступен — работаю на Y» / «все недоступны».
ПОДКЛЮЧЁН Kilo Code (работает из Беларуси!) как АКТИВНЫЙ провайдер: URL
https://kilocode.ai/api/openrouter/chat/completions, ключ — JWT (в app_settings, не в репо), модель
nvidia/nemotron-3-ultra-550b-a55b:free (бесплатно, чистый русский + LaTeX). Gemini остался вторым (failover).
Гочи Kilo на этом ключе: публичные :free (deepseek/mistral) → 404 «No endpoints»; платные → 401 «need to sign in»
(нет кредитов); kilo-auto/free → пустой ответ; рабочие бесплатные: nvidia/nemotron-3-ultra-550b-a55b:free и
openrouter/owl-alpha. Наш callLLM (без HTTP-Referer) Kilo принимает. nemotron — reasoning-модель → в промпт добавлено
«не выводи рассуждения вслух» (commit d1be2c1). Список моделей Kilo: GET .../api/openrouter/models (342 шт).
Админка (games.js, карточка): тумблер RAG, «Переиндексировать», число фрагментов. Кэш assistant_cache
(7 дней, только вопросы без контекста/истории) + счётчик assistant_usage (ИИ/кэш/FAQ, в админке).
Учитель: role в /context, доп. системный промпт для teacher/admin + teacher-чипы в «Спроси».
Ключ перенесён в БД (app_settings assistant_llm_url/key/model), из backend/.env удалён — конфиг
теперь только через админку. НЕ сделано: headless-RAG для JS-учебников; голосовой ввод; редактор промпта.
Связано: reference_quick_lesson reference_student_materials feedback_no_emoji.