Журнал
by commelias
README.md
# Сервис «Быт»
Обвязка для Telegram-агента «Быт» на платформе AI-агентов Timeweb Cloud. Даёт агенту то, чего
у платформы нет: журнал с цифрами, точный православный календарь, напоминания по расписанию
и доставку точных текстов мимо модели.
## Из чего состоит
| Часть | Что делает |
|---|---|
| `app/mcp_server.py` | MCP-сервер «Журнал» — инструменты агента: записать еду/воду/тренировку/отметку, прочитать итог, завести напоминание, сохранить и отправить точный текст |
| `app/scheduler.py` | Часы: раз в минуту складывает в очередь то, что подошло по времени, и отправляет очередь |
| `app/orthodox.py` | Пасха по формуле, посты, сплошные седмицы, двунадесятые праздники |
| `app/db.py` | Журнал в PostgreSQL (или SQLite для локальной проверки) |
| `app/telegram.py` | Отправка в Telegram через Bot API; длинный текст уходит частями |
| `app/http.py` | Единственный исходящий HTTP-клиент: повторы, таймауты, IPv4 |
| `app/agent.py` | Вызов агента Timeweb, чтобы вечерний итог был написан его голосом |
| `main.py` | Всё вместе: HTTP-сервис на порту 8080, `/mcp` закрыт токеном, `/diag` — диагностика |
## Как устроена доставка
Ничего не отправляется на месте. Всё, что сервис говорит человеку, кладётся в таблицу `outbox`,
а единственный воркер в планировщике забирает очередь, шлёт и повторяет при сбое (до пяти раз
с растущей паузой). Отсюда три следствия: вызов инструмента не ждёт Telegram и не упирается
в таймаут; длинный текст режется на части при отправке, а не обрывается; журнал доставки
пишется в одном месте, и агент видит в `context`, что именно сервис уже прислал.
## Событие — единица планировщика
Системные и заведённые человеком события лежат в одной таблице `events`. У события четыре стрелки:
| Поле | Что это |
|---|---|
| `at`, `days`, `repeat_hours`, `max_per_day` | **когда**: время и дни, либо «не чаще чем раз в N часов, не больше M раз в день» |
| `cond`, `param` | **условие**: пусто (просто по времени) либо имя из закрытого списка — `workout_planned`, `workout_unlogged`, `fast_tomorrow`, `no_meals`, `no_water` |
| `doc_kind`, `doc` | **документ**: `text` — текст в событии, `saved` — точный текст из `texts`, `calc` — вычисляемый обработчик (итог дня считает калории) |
| `mark` | **отметка**: что записать в журнал, когда человек ответит. Пока ответа нет, агент видит в `context` строку «спросил и ждёт ответа» |
Условия и вычисления — короткий закрытый список в коде: сделать их данными значит завести
свой язык, а это дороже задачи. Всё остальное — данные: агент заводит, меняет и выключает
события через `add_event` / `edit_event` / `remove_event`, без правки кода и без развёртывания.
Разовые напоминания живут отдельно (`remind_me`): у них нет ни условия, ни документа, только время.
`reminders_sent` гарантирует, что событие уходит один раз в день.
## Точные тексты
Таблица `texts`: молитвенное правило, программа тренировок, любой текст, который должен дойти
слово в слово. Агент его не пересказывает и даже не получает — только сохраняет (`saved_text`)
и отправляет (`send_saved_text`). Так текст не обрывается по лимиту ответа и не переписывается.
## Тренировки
Базовое расписание — дни недели в настройке `workout_days`. Перенос, пропуск и дополнительная
тренировка живут в таблице `workout_exceptions` и заводятся через `move_workout`. Вечером,
если тренировка в плане и не записана, сервис спрашивает о ней сам.
## Переменные окружения
См. `.env.example`. Обязательные: `TELEGRAM_BOT_TOKEN`, `TELEGRAM_CHAT_ID`, `MCP_TOKEN`,
`DATABASE_URL`. `AGENT_API_URL` и `AGENT_API_TOKEN` — по желанию: без них вечерний итог уходит
сухой сводкой.
## Подключение к агенту
В панели агента → MCP-серверы → добавить: URL `https://<домен приложения>/mcp`, транспорт
Streamable HTTP, авторизация Bearer, токен = `MCP_TOKEN`. После обновления кода: «Обновить
методы», затем включить новые инструменты — они приходят выключенными.
## Локальный запуск
```
pip install -r requirements.txt
MCP_TOKEN=test python main.py
```
Без `DATABASE_URL` журнал пишется в файл `byt.db` рядом.
This server cannot be deployed
Maintenance
ActivityMaintained
ResponsivenessNo issues