- Python 93%
- Nix 7%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
Прошедшие записи расписания больше не показываются (дата без года: кандидат дальше трёх дней в будущем — прошлогодний). /clear заводит новый ephemeral-чат, не трогая ленту, — положение дел уезжает Еве заново первым туром. /model: список моделей ядра, выбор на сессию (пер-туровый model), сброс через «/model -»; дефолт — [kernel] model / HM-опция model как surface_model. Команды — через меню с автокомплитом (↑/↓, tab, enter), как в eva-tui. В примерах <вещество> вместо конкретики; README — гайд без Nix. Co-Authored-By: Eva |
||
| eva_redose | ||
| tests | ||
| .gitignore | ||
| flake.lock | ||
| flake.nix | ||
| pyproject.toml | ||
| README.md | ||
eva-redose
AI-first клиент redose: чат с Евой вместо форм и экранов. Журнал ведётся разговором — «принял <вещество> 60 мг интраназально», «накрывает на 7», «начался спад» — Ева записывает через журнальные тулы и предостерегает, когда толерантность ещё высока или запас уходит в минус.
Интерфейс
Одна колонка, как в eva-tui --code: лента + строка ввода. Пока марафона нет —
лобби: приглашение начать и что по расписанию (давно прошедшие записи не
показываются); «давай начнём марафон: <вещество>, 1000 мг в запасе» или «давай
начнём запланированный марафон» — Ева стартует (спонтанный или сегодняшний по
плану), и экран сам переключается на марафонский HUD, разговор остаётся в ленте.
С активным марафоном сверху — живой HUD, обновляется каждую секунду:
Марафон #3 · спонтанный · идёт 5ч 12м
запас: Мефедрон 1840/2000 мг
💊 Мефедрон 60 мг · Интраназально · 14:32 (32м назад) · редоз: через 28м
фаза: плато ▓▓▓▓▓░░░░░░░ 0:42:10 · след: спад через 1ч 05м
Журнальные события — свои и чужие (соседний redose TUI, MCP-сервер) — падают
в ленту dim-строками: база одна, WAL, изменения ловятся по data_version.
Команды — по / с автокомплитом (↑/↓ выбор, tab дополнить, enter выполнить):
/new — новый чат с чистым экраном, /clear — сброс контекста Евы (положение
дел текущего марафона уедет ей заново первым же сообщением), /model — список
моделей ядра, /model <имя> — модель на сессию, /model - — сброс к дефолту,
/status /log /help /quit. esc прерывает ответ, сообщения во время
тура встают в очередь.
Как это устроено
Поверхность ядра Евы:
surface: "redose", чаты ephemeral — ядро жнёт их по TTL простоя,
привязок на диске нет. Каждый тур несёт context (стабильная английская
рамка, кэшируется провайдером) и <state of affairs> — живое положение дел
в теле сообщения, только когда изменилось (рецепт mtl).
Журнал живёт за одним из двух бэкендов:
- remote (
[redose] mcp = "https://…/redose") — канонический журнал у ядра. Пишет только Ева, своимиmcp_redose_*-руками; клиент поллитget_status/get_logчерез тот же redose-mcp (streamable HTTP,X-Redose-Token) и рисует HUD с лентой. Свои тулы не объявляются — у журнала одно перо. - local (без
mcp) — база redose на этой же машине. Тур объявляетextra_tools(journal_trip,journal_note,journal_phase,journal_start— план по номеру или имени,journal_end,journal_status,journal_log,journal_substance,journal_scheduled,journal_plans), исполняет их сама поверхность черезredose.actions; HUD секундный, прямо из базы.
Запуск
Nix (флейк тянет redose сам):
nix run git+https://git.desu.church/eva/redose.git
nix develop # dev shell: python + redose + textual + httpx + pytest
nix build # ./result/bin/eva-redose
Или по-старинке:
pip install -e ../redose -e .
eva-redose
eva-redose --url http://host:8090 --token-file ~/.eva-token --db /tmp/test.db
Конфиг: ~/.config/eva-redose/config.toml
[kernel]
url = "https://eva.desu.church/"
token_file = "/run/secrets/eva-token"
# model = "moonshotai/kimi-k3" # дефолтная модель поверхности; /model сильнее
[redose] # секция есть → remote-режим
mcp = "https://eva.desu.church/redose"
mcp_token_file = "/run/secrets/redose-token"
# или local-режим: без mcp, опционально db = "/path/to/redose.db"
Env: EVA_REDOSE_URL, EVA_REDOSE_TOKEN(_FILE), EVA_REDOSE_MCP_URL,
EVA_REDOSE_MCP_TOKEN(_FILE); CLI --url --token-file --mcp --mcp-token-file --db сильнее всего.
Home-manager модуль (homeManagerModules.default):
programs.eva-redose = {
enable = true;
kernel = "https://eva.desu.church/";
tokenFile = "/run/secrets/eva-token"; # строки-пути, не в стор
redoseMcp = "https://eva.desu.church/redose";
redoseMcpTokenFile = "/run/secrets/redose-token";
# model = "moonshotai/kimi-k3";
# либо local-режим: db = "/var/lib/redose/redose/redose.db";
};
Сетап без Nix
Нужен Python ≥ 3.11 и два пакета (redose — библиотекой, с PyPI он не ставится):
python -m venv ~/.local/share/eva-redose-venv
~/.local/share/eva-redose-venv/bin/pip install \
git+https://git.desu.church/nero/redose.git \
git+https://git.desu.church/eva/redose.git
ln -s ~/.local/share/eva-redose-venv/bin/eva-redose ~/.local/bin/
Дальше — конфиг ~/.config/eva-redose/config.toml как выше. Для remote-режима
положи токены в файлы (например, ~/.config/eva-redose/eva-token и
redose-token, chmod 600) и укажи их в token_file / mcp_token_file.
Что должно быть на стороне сервера: ядро Евы за обратным прокси с
X-Eva-Token, и — для remote-режима — redose-mcp, опубликованный тем же
прокси с X-Redose-Token (см. redose-mcp --transport http). Если ядра под
рукой нет, а redose стоит локально, — просто не указывай [redose] mcp:
клиент будет вести локальную базу сам (local-режим), ядру хватит url.
Тесты
pytest -q # в dev shell; в сборке пакета гоняются сами