docs: add design spec, implementation plan, test plan; update gitignore
This commit is contained in:
@@ -0,0 +1,196 @@
|
||||
# Telegram Bot для управления сессиями Claude Code
|
||||
|
||||
## Обзор
|
||||
|
||||
Персональный Telegram-бот для управления сессиями Claude Code, запущенными на локальном сервере. Позволяет создавать, останавливать, переключать сессии для разных проектов и вести полноценный диалог с Claude через Telegram.
|
||||
|
||||
## Решения
|
||||
|
||||
- **Подход:** Claude Agent SDK (`@anthropic-ai/claude-agent-sdk`) — программный контроль сессий из одного процесса
|
||||
- **Пользователь:** один (персональный бот)
|
||||
- **Взаимодействие:** полноценный чат — сообщения в Telegram отправляются как промпты в активную сессию
|
||||
- **Управление проектами:** быстрый старт по пути + именованные закладки
|
||||
- **Мультисессия:** одна активная сессия получает сообщения, переключение через `/switch` или inline-кнопки
|
||||
- **Вывод:** только финальный результат (без стриминга промежуточных шагов)
|
||||
|
||||
## Архитектура
|
||||
|
||||
```
|
||||
┌─────────────┐ Telegram Bot API ┌──────────────────────┐
|
||||
│ Telegram │◄───────────────────────►│ Bot Server │
|
||||
│ (владелец) │ │ (Bun + TypeScript) │
|
||||
└─────────────┘ │ │
|
||||
│ ┌────────────────┐ │
|
||||
│ │ Session Manager │ │
|
||||
│ │ - activeSession│ │
|
||||
│ │ - sessions map │ │
|
||||
│ │ - projects map │ │
|
||||
│ └───────┬────────┘ │
|
||||
│ │ │
|
||||
│ ┌───────▼────────┐ │
|
||||
│ │ Claude Agent SDK│ │
|
||||
│ │ query({ │ │
|
||||
│ │ prompt, │ │
|
||||
│ │ cwd, │ │
|
||||
│ │ resume, │ │
|
||||
│ │ allowedTools │ │
|
||||
│ │ }) │ │
|
||||
│ └────────────────┘ │
|
||||
└──────────────────────┘
|
||||
│
|
||||
┌──────────▼──────────┐
|
||||
│ Файловая система │
|
||||
│ сервера (проекты) │
|
||||
└─────────────────────┘
|
||||
```
|
||||
|
||||
**Три компонента:**
|
||||
|
||||
1. **Telegram Bot** (grammy) — принимает сообщения, отправляет ответы, inline-кнопки
|
||||
2. **Session Manager** — CRUD сессий, переключение, закладки проектов, персистентность
|
||||
3. **Claude Agent SDK** — выполнение запросов, управление session ID, resume
|
||||
|
||||
**Стек:** TypeScript, Bun, grammy, @anthropic-ai/claude-agent-sdk
|
||||
|
||||
## Команды бота
|
||||
|
||||
### Управление сессиями
|
||||
|
||||
| Команда | Описание |
|
||||
|---------|----------|
|
||||
| `/start <path или name>` | Создать новую сессию для проекта |
|
||||
| `/stop` | Остановить текущую активную сессию |
|
||||
| `/stop <name>` | Остановить конкретную сессию |
|
||||
| `/stopall` | Остановить все сессии |
|
||||
| `/switch <name>` | Переключиться на другую активную сессию |
|
||||
| `/sessions` | Список активных сессий с inline-кнопками для переключения |
|
||||
| `/status` | Статус текущей сессии (idle/busy, проект, cwd) |
|
||||
|
||||
### Управление проектами (закладки)
|
||||
|
||||
| Команда | Описание |
|
||||
|---------|----------|
|
||||
| `/save <name> <path>` | Сохранить закладку проекта |
|
||||
| `/remove <name>` | Удалить закладку |
|
||||
| `/projects` | Список закладок с inline-кнопками для запуска |
|
||||
|
||||
### Прочее
|
||||
|
||||
| Команда | Описание |
|
||||
|---------|----------|
|
||||
| `/help` | Справка по командам |
|
||||
|
||||
### Обычные сообщения
|
||||
|
||||
Текст без `/` отправляется как промпт в текущую активную сессию.
|
||||
|
||||
### Inline-кнопки
|
||||
|
||||
- `/sessions` — кнопки с именами сессий для быстрого переключения
|
||||
- `/projects` — кнопки "Запустить <name>" для быстрого старта сессии
|
||||
|
||||
### Обработка ошибок
|
||||
|
||||
- Сообщение без активной сессии → "Нет активной сессии. Используй /start"
|
||||
- Сообщение пока сессия busy → "Сессия занята, дождись ответа"
|
||||
- `/start` с уже существующим именем → предложить `/switch`
|
||||
|
||||
## Модель данных
|
||||
|
||||
Состояние хранится в `~/.claude-telegram-bot/state.json`:
|
||||
|
||||
```typescript
|
||||
interface AppState {
|
||||
// Закладки проектов
|
||||
projects: Record<string, string>; // name → absolute path
|
||||
|
||||
// Активные сессии
|
||||
sessions: Record<string, { // name → session info
|
||||
sessionId: string; // ID из Claude Agent SDK
|
||||
cwd: string; // рабочая директория
|
||||
status: "idle" | "busy";
|
||||
}>;
|
||||
|
||||
// Какая сессия сейчас принимает сообщения
|
||||
activeSession: string | null; // name из sessions
|
||||
}
|
||||
```
|
||||
|
||||
**Персистентность:**
|
||||
- Записывается при каждом изменении
|
||||
- При старте бота загружается из файла
|
||||
- `sessions` при рестарте: sessionId сохраняются, при следующем сообщении пробуем resume — если не удаётся, сообщаем пользователю
|
||||
- `projects` переживают перезапуск полностью
|
||||
|
||||
**Именование сессий:**
|
||||
- `/start /d/my-project` → имя из последнего сегмента пути: `my-project`
|
||||
- `/start mybot` (закладка) → имя = имя закладки
|
||||
- Конфликт имён → суффикс: `my-project-2`
|
||||
|
||||
## Обработка сообщений
|
||||
|
||||
```
|
||||
Telegram сообщение
|
||||
│
|
||||
├─ начинается с "/" → парсинг команды → выполнение
|
||||
│
|
||||
└─ обычный текст → отправка в активную сессию:
|
||||
1. Проверить activeSession != null
|
||||
2. Проверить session.status === "idle"
|
||||
3. Поставить status = "busy"
|
||||
4. Отправить typing индикатор
|
||||
5. query({ prompt: text, resume: sessionId })
|
||||
6. Собрать финальный ResultMessage
|
||||
7. Отправить ответ (разбить на чанки если > 4096 символов)
|
||||
8. Поставить status = "idle"
|
||||
При ошибке → сообщение об ошибке, вернуть status = "idle"
|
||||
```
|
||||
|
||||
**Разбивка длинных ответов:**
|
||||
- Лимит Telegram — 4096 символов
|
||||
- Разбиваем по границам `\n\n`, затем `\n`
|
||||
- Markdown-форматирование в каждом чанке
|
||||
|
||||
## Безопасность
|
||||
|
||||
- **Allowlist по chat_id** — бот отвечает только владельцу (TELEGRAM_OWNER_ID), остальных игнорирует
|
||||
- **Permissions для Claude Agent SDK** — `permissionMode: "bypassPermissions"` (персональный бот, интерактивный approval нецелесообразен)
|
||||
- **Без валидации путей** — единственный пользователь, ограничение файловой системы не нужно
|
||||
|
||||
## Конфигурация
|
||||
|
||||
Файл `.env`:
|
||||
|
||||
```
|
||||
TELEGRAM_BOT_TOKEN=<токен от BotFather>
|
||||
TELEGRAM_OWNER_ID=<твой Telegram user ID>
|
||||
ANTHROPIC_API_KEY=<API ключ Anthropic>
|
||||
```
|
||||
|
||||
## Структура проекта
|
||||
|
||||
```
|
||||
claude-telegram-bot/
|
||||
├── src/
|
||||
│ ├── index.ts # Точка входа
|
||||
│ ├── bot.ts # grammy Bot, middleware owner check, хендлеры
|
||||
│ ├── handlers/
|
||||
│ │ ├── commands.ts # Хендлеры команд
|
||||
│ │ └── message.ts # Текстовые сообщения → Claude
|
||||
│ ├── services/
|
||||
│ │ ├── session-manager.ts # CRUD сессий, переключение
|
||||
│ │ └── claude.ts # Обёртка Claude Agent SDK
|
||||
│ ├── state/
|
||||
│ │ └── store.ts # Загрузка/сохранение state.json
|
||||
│ └── utils/
|
||||
│ └── telegram.ts # Разбивка сообщений, форматирование
|
||||
├── .env
|
||||
├── package.json
|
||||
├── tsconfig.json
|
||||
└── README.md
|
||||
```
|
||||
|
||||
## Git
|
||||
|
||||
- Репозиторий: `http://localhost:3000/admin/claude-telegram-bot`
|
||||
- Инициализация git при создании проекта, push в remote по завершении
|
||||
Reference in New Issue
Block a user