Fix HOME volume mount, genericize topic, add progress statuses, extract lexicon

- Volume was mounted at ~/.claude only, but claude-code writes auth to
  ~/.claude.json too — that file lived on the ephemeral container layer and
  was lost on every recreate. Now the whole $HOME is on the named volume,
  and claude-config moved outside HOME (/app) so it isn't shadowed by it.
- Default /news topic was hardcoded to AI; now it's a configurable
  DEFAULT_TOPIC (plain "главные новости дня"), topic is fully free-form.
- Prompt now instructs Claude to send interim " ..." progress updates via
  send_to_telegram while researching, not just the final digest — a bare
  request like "call this tool" was already taking 3+ minutes end-to-end,
  so silence read as broken.
- All user-facing/prompt text moved into bot/lib/lexicon.dart.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
2026-07-21 21:53:38 +03:00
parent cb2041fc56
commit 7bfe0dfe0c
8 changed files with 93 additions and 52 deletions

View File

@@ -8,11 +8,15 @@ Telegram-бот на Dart: по команде `/news` (или `/news <тема>
Один контейнер, три процесса:
1. `agent-news-bot` (Dart, long polling) — слушает `/news`, спавнит `claude` как сабпроцесс.
2. `claude` (Claude Code CLI) — делает ресёрч, в конце вызывает MCP-тул `send_to_telegram`.
1. `agent-news-bot` (Dart, long polling) — слушает `/news <тема>`, спавнит `claude` как сабпроцесс.
2. `claude` (Claude Code CLI) — делает ресёрч; по ходу и в конце сам вызывает MCP-тул
`send_to_telegram` (промежуточные статусы + финальная выжимка).
3. `agent-news-mcp` (Dart, stdio MCP-сервер) — спавнится самим `claude`, шлёт готовый
текст в Telegram Bot API.
Все тексты, которые бот показывает пользователю или подставляет в промпт Claude, лежат
в одном месте — `bot/lib/lexicon.dart`.
## Запуск локально
```bash
@@ -31,16 +35,20 @@ Claude Code CLI использует OAuth-логин через Claude.ai (по
после первого запуска нужно зайти в контейнер и залогиниться:
```bash
docker compose exec agent-news claude
docker compose exec agent-news claude auth login
```
CLI напечатает ссылку — открой её в браузере, авторизуйся. Токен сохранится в
`~/.claude` на volume, так что после `docker compose restart` логин не слетит.
CLI напечатает ссылку — открой её в браузере, авторизуйся, вставь код обратно в
терминал, если попросит. Учти: и `~/.claude/`, и `~/.claude.json`оба нужны для
логина, поэтому в volume смонтирован **весь `/home/agent`** (см. `docker-compose.yml`),
не только `~/.claude/`. После `docker compose restart` логин не слетит.
### Проверка
Напиши боту `/news` (или `/news <тема>`) из чата с id из `ALLOWED_CHAT_IDS` — бот
ответит "ищу…", а через 1-3 минуты Claude сам пришлёт выжимку через `send_to_telegram`.
Напиши боту `/news <тема>` (или просто `/news` — возьмёт `DEFAULT_TOPIC`) из чата с id
из `ALLOWED_CHAT_IDS`. Бот сразу ответит "начинаю…", дальше Claude сам присылает статусы
по ходу ресёрча и в конце — готовую выжимку, всё через `send_to_telegram`. Ресёрч
занимает несколько минут — это нормально, статусы как раз для этого.
```bash
docker compose logs -f agent-news
@@ -59,6 +67,6 @@ cd ../mcp_server && dart pub get && dart analyze
|---|---|---|
| `TELEGRAM_BOT_TOKEN` | да | токен бота, используется и ботом, и MCP-сервером |
| `ALLOWED_CHAT_IDS` | да | список chat_id через запятую — кому отвечает бот |
| `NEWS_PROMPT` | нет | промпт по умолчанию для `/news` без темы |
| `CLAUDE_TIMEOUT_SECONDS` | нет | таймаут на ресёрч (по умолчанию 360) |
| `MCP_CONFIG_PATH` | нет | путь к `mcp.json` (по умолчанию `/home/agent/claude-config/mcp.json`) |
| `DEFAULT_TOPIC` | нет | тема для `/news` без аргумента (по умолчанию — «главные новости дня») |
| `CLAUDE_TIMEOUT_SECONDS` | нет | таймаут на ресёрч (по умолчанию 600) |
| `MCP_CONFIG_PATH` | нет | путь к `mcp.json` (по умолчанию `/app/claude-config/mcp.json`) |