feat: xterm.js + node-pty architecture for Claude CLI web terminal
Complete rewrite from tmux + JSONL parsing to a clean PTY-based approach. The proxy spawns Claude CLI in a pseudo-terminal via node-pty and relays terminal I/O as binary WebSocket frames to the simple-chat backend, which forwards them to the browser where xterm.js renders a full terminal. - node-pty PTY manager with 50KB replay buffer per session - Binary frame protocol with chatId multiplexing - WebSocket client with auto-reconnection and heartbeat - Directory listing and session listing for the web UI - README with setup instructions Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
117
REQUIREMENTS.md
Normal file
117
REQUIREMENTS.md
Normal file
@ -0,0 +1,117 @@
|
||||
# Claude CLI Proxy — Требования
|
||||
|
||||
## Функциональные требования
|
||||
|
||||
### FR-1: WebSocket-соединение с бэкендом
|
||||
|
||||
- Подключение к бэкенду simple-chat через WebSocket по настраиваемому URL
|
||||
- Аутентификация с помощью `PROXY_TOKEN`
|
||||
- Отправка идентификации устройства при подключении
|
||||
- Поддержание постоянного соединения с автоматическим переподключением
|
||||
|
||||
### FR-2: Управление tmux-сессиями
|
||||
|
||||
- Управление одной tmux-сессией (настраиваемое имя, по умолчанию `claude-proxy`)
|
||||
- Создание новых tmux-окон по запросу (одно на чат)
|
||||
- Запуск `claude` CLI в новых окнах или `claude --resume <sessionId>` для существующих сессий
|
||||
- Закрытие окон при завершении чатов
|
||||
- Отправка нажатий клавиш в окна (сообщения пользователя, клавиши)
|
||||
- Захват содержимого панели для скриншотов
|
||||
|
||||
### FR-3: Мониторинг JSONL-транскриптов
|
||||
|
||||
- Отслеживание JSONL-файлов транскриптов Claude CLI на предмет нового содержимого
|
||||
- Инкрементальное чтение с отслеживанием смещения в байтах (без полного перечитывания)
|
||||
- Парсинг JSONL-записей: сообщения пользователя, сообщения ассистента, вызовы инструментов, результаты инструментов
|
||||
- Фильтрация системных/внутренних сообщений (события инициализации, конфигурации)
|
||||
- Определение правильного пути к файлу через карту сессий и закодированную рабочую директорию
|
||||
- Интервал опроса: 2 секунды
|
||||
|
||||
### FR-4: Мониторинг строки состояния терминала
|
||||
|
||||
- Захват последних 3 строк каждой активной tmux-панели
|
||||
- Парсинг строки состояния для извлечения:
|
||||
- Названия проекта
|
||||
- Названия модели и размера контекстного окна
|
||||
- Процента использования контекста
|
||||
- Процентов использования сессии и недели
|
||||
- Режима разрешений
|
||||
- Обнаружение интерактивных состояний UI (запросы разрешений, запросы ввода)
|
||||
- Интервал опроса: 1 секунда
|
||||
|
||||
### FR-5: Маппинг сессий через хук
|
||||
|
||||
- Установка хука SessionStart в настройках Claude CLI (`~/.claude/settings.json`)
|
||||
- Хук захватывает sessionId и текущий tmux windowId при запуске Claude CLI
|
||||
- Сохранение маппинга в `~/.claude-proxy/session_map.json`
|
||||
- Чтение карты сессий для нахождения JSONL-файлов активных окон
|
||||
|
||||
### FR-6: Выполнение команд
|
||||
|
||||
- Выполнение произвольных команд в tmux-панелях по запросу бэкенда
|
||||
- Захват вывода команды и возврат на бэкенд (`send_command_capture`)
|
||||
|
||||
### FR-7: Список директорий и сессий
|
||||
|
||||
- Получение списка доступных рабочих директорий по запросу
|
||||
- Получение списка возобновляемых сессий Claude CLI по запросу
|
||||
|
||||
### FR-8: Скачивание файлов
|
||||
|
||||
- Скачивание файлов по URL из MinIO, на которые есть ссылки в сообщениях
|
||||
- Обеспечение доступа к файлам через веб-интерфейс
|
||||
|
||||
### FR-9: Синхронизация состояния
|
||||
|
||||
- При переподключении отправка полного состояния всех активных окон на бэкенд (`sync_state`)
|
||||
- Отчёт о создании окон (`window_ready`) и их закрытии (`window_closed`)
|
||||
|
||||
## Нефункциональные требования
|
||||
|
||||
### NFR-1: Надёжность
|
||||
|
||||
- Переподключение к бэкенду с экспоненциальной задержкой при разрыве соединения
|
||||
- Возобновление мониторинга после переподключения без потери состояния
|
||||
- Корректная обработка падений tmux-процессов
|
||||
- Обработка отсутствующих или повреждённых JSONL-файлов без аварийного завершения
|
||||
|
||||
### NFR-2: Производительность
|
||||
|
||||
- Опрос терминала с интервалом 1 секунда не должен вызывать заметную нагрузку на CPU
|
||||
- Опрос JSONL с интервалом 2 секунды использует отслеживание смещения в байтах, чтобы не перечитывать файлы целиком
|
||||
- Кеш mtime полностью пропускает неизменённые файлы
|
||||
- Эффективные tmux-операции через прямой `execFile` (без накладных расходов на shell)
|
||||
|
||||
### NFR-3: Переносимость
|
||||
|
||||
- Работает на macOS (основная машина разработчика)
|
||||
- Требования: Node.js, tmux, Claude CLI (`claude` в PATH)
|
||||
- Без Docker, без пайплайна деплоя
|
||||
|
||||
### NFR-4: Безопасность
|
||||
|
||||
- Аутентификация по токену для WebSocket-соединения
|
||||
- Отсутствие слушающих портов (только исходящие соединения)
|
||||
- Карта сессий хранится локально без удалённого доступа
|
||||
|
||||
### NFR-5: Поддерживаемость
|
||||
|
||||
- TypeScript со строгой типизацией
|
||||
- Общие конфиги из @vigdorov/dev-configs (ESLint, Prettier, TSConfig)
|
||||
- Модульная структура: connection, tmux, monitor, hook, files
|
||||
|
||||
## Обработка граничных случаев
|
||||
|
||||
| Сценарий | Поведение |
|
||||
|----------|-----------|
|
||||
| Бэкенд недоступен при запуске | Повтор с экспоненциальной задержкой |
|
||||
| Бэкенд отключается во время сессии | Переподключение и синхронизация состояния |
|
||||
| JSONL-файл ещё не создан | Пропуск мониторинга, повтор при следующем опросе |
|
||||
| JSONL-файл удалён или перемещён | Сброс смещения в байтах, повторное обнаружение |
|
||||
| tmux-сессия не запущена | Автоматическое создание сессии |
|
||||
| Процесс tmux-окна завершился | Обнаружение через захват, отчёт `window_closed` |
|
||||
| Карта сессий отсутствует | Создание пустого файла карты |
|
||||
| Хук не установлен | Автоустановка при запуске прокси |
|
||||
| Конфликт нескольких прокси | Один прокси на tmux-сессию по дизайну |
|
||||
| Большие JSONL-файлы | Инкрементальное чтение через смещение в байтах, без полного перечитывания |
|
||||
| Claude CLI отсутствует в PATH | Ошибка при создании окна, отчёт на бэкенд |
|
||||
Reference in New Issue
Block a user