From 6dc6b51b94a6120a5a09cb70098522e1fd412b77 Mon Sep 17 00:00:00 2001 From: andrew Date: Wed, 2 Sep 2026 16:40:56 +0300 Subject: [PATCH] Add README.md --- README.md | 282 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 282 insertions(+) create mode 100644 README.md diff --git a/README.md b/README.md new file mode 100644 index 0000000..ca21510 --- /dev/null +++ b/README.md @@ -0,0 +1,282 @@ +# selectel-ml-tui + +TUI-приложение (Python 3.10+) для отображения потребления **ИИ-роутера Selectel** +прямо в терминале. Работает на Ubuntu (22.04+/24.04) и macOS (12+). + +## Возможности + +- Дашборд потребления за месяц (сумма, запросы, input/output/cache токены) +- Метрики за 24 часа (доступность, TTFT, задержка) — общие и по моделям +- Бюджет роутера (лимит/расход/остаток) и лимиты по API-ключам +- История потребления по дням с Unicode-бар-графиком (локальный SQLite-кэш) +- Детализация метрик конкретной модели (Enter в таблице моделей) +- Офлайн-режим: при недоступности API показывает последние данные из кэша +- Автообновление по интервалу из конфигурации (по умолчанию 60 с) +- Экспорт истории в CSV/JSON, диагностика окружения (`doctor`) + +## Интерфейс + +``` +┌─ Selectel ML Tokens ──────────────── online · 1 186,73 ₽ ───────┐ +│ ┌─ Потребление за месяц ─┐ ┌─ Метрики за 24 часа ──────────────┐ │ +│ │ Сумма: 1 186,73 ₽ │ │ Доступность: 100,0% │ │ +│ │ Запросы: 1 096 │ │ TTFT: 3 670,0 мс │ │ +│ │ Токены: 482 749 246 │ │ Запросы: 1 097 │ │ +│ │ Input: 244 004 716 │ │ Input/Output/Cache: … │ │ +│ │ Output/Cache: … │ └───────────────────────────────────┘ │ +│ │ Бюджет: 2 000 ₽ │ │ +│ └────────────────────────┘ │ +│ По моделям │ +│ ┌──────────────────────────────────────────────────────────────┐ │ +│ │ Модель │ Запросы │ Доступность │ TTFT, мс │ Задержка, мс │ │ +│ │ deepseek-v4-pro │ 1028 │ 100,0% │ 3,69 │ 12,29 │ │ +│ └──────────────────────────────────────────────────────────────┘ │ +│ r — обновить h — история k — ключи s — настройки q — выход │ +└──────────────────────────────────────────────────────────────────┘ +``` + +Экран **История** (**h**): бар-график стоимости по дням + таблица +(период 7/30/90 дней — кнопками). Экран **Ключи** (**k**): лимиты и расход по +API-ключам. Экран **Настройки** (**s**): интервал обновления, «Очистить кэш», +пути и маскированный токен. **Esc** — назад. + +## Горячие клавиши + +| Клавиша | Действие | +|---|---| +| `r` | Обновить данные | +| `h` | История потребления | +| `k` | API-ключи и лимиты | +| `s` | Настройки | +| `q` | Выход | +| `Esc` | Назад (с экрана истории/настроек/модели) | +| `Enter` / клик | Детализация метрик модели (в таблице «По моделям») | + +На macOS горячие клавиши — обычные символьные (`r/h/s/q`); Option/Command +зарезервированы системой и не используются. + +## Требования + +- Python 3.10+ +- Ubuntu 22.04+/24.04, macOS 12+ +- Терминал с поддержкой цвета и UTF-8 (GNOME Terminal, Konsole, tmux, + Terminal.app, iTerm2) + +## Источники данных + +- **Billing Statistics API** (`https://api.selectel.ru`, заголовок `X-Token`): + стоимость потребления ИИ-роутера (провайдер `aig`) по дням/часам. Параметры + `start`/`end` принимаются в полном ISO-формате (`YYYY-MM-DDTHH:MM:SS.000`), + короткие даты дополняются клиентом автоматически. Значение `value` в копейках. +- **Gateway API ИИ-роутера** (`/aig/gateway/v1/*`, IAM-токен проекта + `X-Project-Id`): + токены, метрики, каталог моделей. +- **IAM-авторизация**: `POST https://cloud.api.selcloud.ru/identity/v3/auth/tokens` + (логин/пароль сервисного пользователя, scope project, TTL 24 ч, кэш с + автообновлением за 5 минут до истечения). + +## Получение токенов (панель Selectel) + +- **Статический токен** (billing-метрики): панель `my.selectel.ru` → профиль → + **Доступ** → **API-ключи**. Вставьте токен в мастер настройки. +- **IAM-токен** (gateway: сумма/токены/модели/ключи): нужен **сервисный + пользователь**. Создайте его в `my.selectel.ru` → **IAM** → **Сервисные + пользователи** (имя без email, например `ml-monitor`), назначьте роль на + нужный ML-проект. Затем в `selectel-ml-tui config` укажите имя сервисного + пользователя, его пароль, `project_id` и `domain_id` (номер аккаунта). + Без сервисного пользователя доступна только стоимость из billing. + +Подробнее об API: [Selectel ML / управление роутером](https://selectel.ru/services/ml/) — +внутренние API панели и документация по биллингу. + +## Установка + +```bash +make install # Ubuntu/macOS +# или +./scripts/install_ubuntu.sh # Ubuntu +./scripts/install_macos.sh # macOS +# или make install-ubuntu / make install-macos +``` + +Всё сводится к двум командам на каждой ОС: + +```bash +# Ubuntu +sudo apt-get update && sudo apt-get install -y python3 python3-venv python3-pip +pip install --user . # или ./scripts/install_ubuntu.sh +``` + +```bash +# macOS +brew install python@3.11 # или ./scripts/install_macos.sh +pip install --user . +``` + +## Запуск + +```bash +make run +# или +.venv/bin/selectel-ml-tui run +# или (с корректным TERM/LANG, подходит для tmux/ssh) +./scripts/run.sh run +``` + +CLI-точка входа: `selectel-ml-tui` (console_scripts), а также `python -m selectel_ml_tui`. + +При первом запуске без настроенных учётных данных выводится подсказка +(`selectel-ml-tui config`); `selectel-ml-tui doctor` предупреждает, что токен +не настроен. + +TUI-дашборд: +- **Dashboard**: потребление за месяц (сумма, токены), метрики за 24 часа, + таблица «По моделям»; статус в заголовке — `online`/`offline` +- **r** — обновить, **h** — история, **s** — настройки, **q** — выход +- Автообновление по интервалу из конфигурации (по умолчанию 60 с) +- При недоступности API показывает последние данные из кэша (офлайн) +- **История** (**h**): таблица по дням из кэша + Unicode-бар-график стоимости, + выбор периода 7/30/90 дней (кнопки) +- **Модель** (Enter/клик в таблице моделей): детализация метрик конкретной модели +- **Настройки** (**s**): изменение интервала обновления (сохранение в конфиг), + «Очистить кэш», пути к конфигу/БД, маскированный токен +- Навигация: **Esc** — назад + +## Конфигурация + +```bash +selectel-ml-tui config # интерактивный мастер настройки +selectel-ml-tui config --path # показать пути конфигурации +selectel-ml-tui config --show # показать текущие настройки (секреты маскируются) +``` + +Настройки хранятся в `config.toml`, учётные данные (пароль сервисного +пользователя, статический токен) — в `credentials.json` в каталоге конфигурации +(права 0600). Каталог: Linux — `~/.config/selectel-ml-tui`, macOS — +`~/Library/Application Support/selectel-ml-tui`. + +Переменные окружения имеют приоритет над файлом конфигурации: + +- `SELCTEL_API_URL` — базовый URL API (вместо `api_base_url`) +- `SELCTEL_TOKEN` — статический токен (вместо `static_token`) +- `SELCTEL_SERVICE_USER`, `SELCTEL_PASSWORD` — сервисный пользователь +- `SELCTEL_PROJECT_ID`, `SELCTEL_DOMAIN_ID` — проект и аккаунт +- остальные поля: `SELCTEL_API_BASE_URL`, `SELCTEL_REFRESH_INTERVAL`, `SELCTEL_ROUTER_ID`, … + +## Локальный кэш и история + +Данные сохраняются в SQLite-базу (`cache.db`) в каталоге данных платформы +(Linux: `~/.local/share/selectel-ml-tui`, macOS: +`~/Library/Application Support/selectel-ml-tui`) при каждом успешном обновлении: +- `consumption_snapshots` — снимки потребления (сумма, токены) +- `metrics_snapshots` — снимки общих метрик +- `model_metrics` — метрики по моделям +- `history` — точки истории по периодам (upsert, без дублей) + +При недоступности API TUI показывает «офлайн» и последние данные из кэша. +Старые записи удаляются автоматически (TTL 180 дней). + +Экспорт истории: `selectel-ml-tui export --format json|csv -o <файл>`. + +## Платформы (Ubuntu и macOS) + +Диагностика окружения: `selectel-ml-tui doctor` — проверяет Python (>=3.10), +`TERM`, `LANG`, кодировку UTF-8, выводит пути к конфигурации и данным. + +Отличия платформ: + +| | Ubuntu 22.04+/24.04 | macOS 12+ | +|---|---|---| +| Python | python3.10+ (apt: `python3 python3-venv python3-pip`) | Homebrew `python@3.11`+ | +| Каталог конфигурации | `~/.config/selectel-ml-tui` | `~/Library/Application Support/selectel-ml-tui` | +| Каталог данных | `~/.local/share/selectel-ml-tui` | `~/Library/Application Support/selectel-ml-tui` | +| Права доступа | 0700/0600 (по умолчанию) | то же; доступ на чтение к `Application Support` | +| Терминалы | GNOME Terminal, Konsole, tmux | Terminal.app, iTerm2 | +| Клавиши | — | hotkeys через Ctrl/символы (r/h/s/q); Option/Command зарезервированы системой | + +Требования к окружению терминала: +- `TERM` должен указывать на цветной терминал (`xterm-256color`, `tmux-256color`). + В `tmux`/`screen` задаётся автоматически; `scripts/run.sh` подставляет + `xterm-256color`, если переменная не задана. +- `LANG`/`locale` должны быть UTF-8 (`ru_RU.UTF-8`, `en_US.UTF-8`), иначе + возможны сбои отображения русского текста и граничных символов (▌▀█). + +CI: GitHub Actions (`ubuntu-latest` + `macos-latest`, Python 3.11/3.12) — ruff, +mypy, pytest+coverage, doctor. + +## Упаковка (однофайловый исполняемый файл) + +Опционально: сборка автономного бинарника через PyInstaller. + +```bash +make build # или ./scripts/build_ubuntu.sh / build_macos.sh +./dist/selectel-ml-tui doctor # проверка +``` + +Артефакт не зависит от установленного Python и venv (собирается на целевой ОС). + +История версий: [CHANGELOG.md](CHANGELOG.md). Финальный чек-лист тестирования: +[docs/FINAL_CHECKLIST.md](docs/FINAL_CHECKLIST.md). + +## Разработка + +```bash +make test # pytest + coverage (порог 80%) +make lint # ruff (flake8/isort/format) +make typecheck # mypy (strict) +make format # ruff format +``` + +- Unit-тесты: config (приоритет env), storage, models (парсинг/форматирование), + API-клиент (httpx.MockTransport: успех, 401, 429, 500, timeout, сетевые ошибки) +- Интеграционный smoke-тест TUI: headless-запуск приложения через `App.run_test()` +- Статический анализ настроен в `pyproject.toml` (`[tool.ruff]`, `[tool.mypy]`, + `fail_under = 80`). + +## FAQ и troubleshooting + +**«Учётные данные не настроены» при запуске** +Выполните `selectel-ml-tui config` — мастер настройки запросит токен +(и опционально сервисного пользователя для метрик моделей). Проверка: +`selectel-ml-tui doctor` → `[OK] token`. + +**Ошибки авторизации (401 / 403)** +- Статический токен истёк или неверен — получите новый в панели Selectel + (профиль → API-токены) и обновите через `selectel-ml-tui config`. +- IAM-доступ: сервисный пользователь должен иметь роль *reader* на нужном + ML-проекте; проверьте `project_id` и `domain_id` (аккаунт). У IAM-токена + TTL 24 ч — приложение обновляет его автоматически (за 5 минут до истечения). + +**В дашборде нет метрик по моделям (Input/Output/Cache отсутствуют)** +Gateway-данные (токены по моделям, каталог моделей) требуют IAM-токена +сервисного пользователя. Если сервисный пользователь не создан, доступна +только стоимость (billing) — на дашборде выводится пояснение +«Токены и модели — только через IAM». Создать сервисного пользователя: +my.selectel.ru → IAM → Сервисные пользователи (с областью доступа на нужный +проект), затем `selectel-ml-tui config`. + +**PermissionError при запуске (`credentials.json` не читается)** +Файлы конфигурации должны принадлежать текущему пользователю (права 0600). +Если запускать приложение от `root`/`sudo`, файлы создаются с владельцем root, +и обычный запуск падает. Исправление (macOS/Linux): +`sudo chown -R $USER ~/Library/Application\ Support/selectel-ml-tui` +(на Linux путь `~/.config/selectel-ml-tui`). Не запускайте приложение от root. + +**Ошибка 422 при запросе данных** +API принимает только полные ISO-таймстампы (`YYYY-MM-DDTHH:MM:SS.000`). +Приложение формирует их самостоятельно; если ошибка повторяется — проверьте +часовой пояс (`doctor` → `LANG`/`locale`). + +**«Краказябры»/битые символы в терминале** +`LANG`/`locale` должны быть UTF-8 (`ru_RU.UTF-8`, `en_US.UTF-8`), `TERM` — +цветной (`xterm-256color`). Запуск через `./scripts/run.sh run` подставит +значения автоматически (полезно в tmux/ssh). + +**Офлайн-режим** +При недоступности API в заголовке появляется `offline`, а дашборд показывает +последние снимки из SQLite-кэша. Данные обновятся автоматически при +восстановлении сети (клавиша `r` — вручную). + +**«Нет данных для графика» в истории** +Кэш пуст — данные появляются после первого успешного обновления (каждая +загрузка сохраняет точку за день). Очистить кэш можно в экране «Настройки» +или через `export` (не очищает).