- Контекст диалога хранит Mastra Memory (LibSQL, memory.db рядом с DB_PATH), тред на чат - Бюджет истории — messageHistory.maxTokens (CONTEXT_TOKEN_LIMIT, по умолчанию 12000) - ToolCallFilter: результаты инструментов не попадают в прошлые реплики, внутри ответа — только свежий шаг - Системный промпт стабилен для всего чата (кешируется провайдером); автор и упоминания — в <turn author_name> - Фото передаются через context и не сохраняются в памяти - maxSteps и maxOutputTokens (ANSWER_TOKEN_LIMIT) — в defaultOptions агента - /context и /clear работают через Memory recall/deleteThread - Удалены свои dialog_messages, dialog-repository и dialog-service Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
51 lines
4.4 KiB
Markdown
51 lines
4.4 KiB
Markdown
# Boltun AI
|
||
|
||
Telegram-бот на Node.js + TypeScript + grammY, AI через Mastra (OpenRouter — по умолчанию Gemini 3.8 Flash, или DeepSeek напрямую). Хранилище — SQLite (better-sqlite3).
|
||
|
||
## Команды
|
||
|
||
- `pnpm dev` — seed личностей + запуск с автоперезагрузкой (читает `.env`)
|
||
- `pnpm seed` / `pnpm seed:dev` — синхронизировать личности из `constants/personas.ts` + `prompts/personas/*.md` с БД
|
||
- `pnpm import-history:dev <result.json>` — загрузить экспорт чата из Telegram Desktop с диска (в проде — `/import` боту)
|
||
- `pnpm typecheck` — проверка типов
|
||
- `pnpm build` / `pnpm start` — сборка в `dist/` и запуск
|
||
- Node.js 24 (`.nvmrc`); Mastra требует Node >= 22.13
|
||
|
||
## Архитектура
|
||
|
||
Зависимости идут сверху вниз: `bot` → `services` → `repositories` → `libs`. Сборка всех слоёв (composition root) — в `src/index.ts`.
|
||
|
||
```
|
||
src/
|
||
index.ts — создание зависимостей и запуск бота
|
||
config.ts — чтение и валидация env
|
||
types.ts — доменные типы (Persona, ChatMessage, ChatMember)
|
||
constants/ — список личностей (id, название) и прочие константы
|
||
scripts/ — отдельные точки входа (seed, import-history)
|
||
libs/ — инфраструктура без бизнес-логики (SQLite и миграции, промпты, форматирование Telegram, парсер экспорта)
|
||
repositories/ — только SQL и маппинг строк в доменные типы, по репозиторию на таблицу
|
||
services/ — бизнес-логика; зависят от репозиториев, не знают про grammY
|
||
assistant/ — AI на Mastra: агент, память (Memory), промпты, tools
|
||
bot/ — grammY: сборка бота, общие хелперы ответа, скачивание фото
|
||
handlers/ — тонкие Composer'ы: разбор команды → вызов сервиса → ответ
|
||
prompts/ — тексты промптов: system.md (правила бота) и personas/<id>.md
|
||
```
|
||
|
||
- Память разделена: архив чата (`messages` в SQLite бота, читается инструментами) и контекст диалога (Mastra Memory, `data/memory.db`, тред на чат). `/clear` чистит только контекст.
|
||
- Где Mastra закрывает потребность (память, бюджет токенов, фильтры, процессоры) — используем Mastra, а не своё.
|
||
- Промпты храним только в `prompts/*.md`, не в коде.
|
||
- Личности не редактируются из чата: источник правды — код и `prompts/`, в БД их кладёт `seed`.
|
||
- Изменения схемы БД — через `migrate` в `libs/db.ts` (у пользователей уже есть базы).
|
||
- Каждый модуль — фабрика `createX(deps)`, тип экспортируется как `ReturnType<typeof createX>`.
|
||
- Хендлеры не ходят в репозитории напрямую — только через сервисы.
|
||
- Правила доступа (только админы) — в `bot/create-bot.ts` через `bot.filter`.
|
||
|
||
## Стиль кода
|
||
|
||
- Пиши функционально: стрелочные функции и фабрики (`const createX = (...) => ({ ... })`), без классов.
|
||
- Не используй ключевое слово `function` — только `const fn = (...) => ...`.
|
||
- Не используй `let` (и `var`) — только `const`; вместо циклов с мутацией — `map`/`filter`/`reduce`/рекурсия.
|
||
- Отделяй пустой строкой объявления констант и логические блоки друг от друга.
|
||
- Импорты локальных файлов — с расширением `.js` (ESM, `module: NodeNext`).
|
||
- Тексты для пользователей бота и комментарии — на русском.
|