# dsh-copilot-quota Индикатор остатка квоты GitHub Copilot для веб-интерфейса [DeepSeek Harness](https://www.npmjs.com/package/@deepseek-ai/dsh). В dsh не было счётчика квоты Copilot: плагин [`dsh-oauth-copilot`](https://www.npmjs.com/package/dsh-oauth-copilot) хранит только грант и список доступных моделей, а ядро показывает лишь ошибку, когда лимит уже исчерпан. Этот плагин закрывает пробел: рядом с кнопкой отправки появляется живой бейдж. ``` Copilot 200/200 ← зелёная точка, клик — обновить ``` ## Что показывает | Элемент | Значение | |---|---| | Точка | Худший остаток по всем измеряемым бакетам: зелёная, жёлтая при ≤ 40 %, красная при ≤ 15 % | | Число | Бакет `chat` в виде `осталось/всего` (если его нет — первый измеряемый бакет) | | Наведение | Логин, тариф и SKU, все бакеты, дата сброса квоты и время последнего обновления | | Клик | Принудительное обновление в обход серверного кэша | Бейдж не отображается, если гранта Copilot нет, — он не показывает метр, которого не существует. По той же причине отбрасываются бакеты `0 из 0`: у бесплатного тарифа нет пула AI-кредитов. ## Требования - DeepSeek Harness `>= 0.1.0-rc.6 < 0.3.0`, профиль `web` (проверено на `0.2.0-rc.2`). - Выполненный вход в Copilot: ```sh npx -y dsh-oauth-copilot login ``` Вход намеренно выполняется человеком из терминала; подробности — в README того пакета. - Только github.com: GitHub Enterprise не поддерживается, как и в `dsh-oauth-copilot`. ## Установка С GitHub (без клонирования и сборки): ```sh dsh plugin --profile web add github:vowa-antilamer/dsh-copilot-quota ``` Из локальной папки: ```sh dsh plugin --profile web add /path/to/dsh-copilot-quota ``` Живой профиль пересобирается сам (серверная половина сразу начинает отдавать маршрут, клиентский бандл — раздаваться); **обновите страницу в браузере**, чтобы загрузился клиентский модуль. Перезапуск `dsh web` нужен, только если после обновления страницы бейджа нет. Удаление: ```sh dsh plugin --profile web remove dsh-copilot-quota ``` ## Настройка Необязательный блок в записи плагина (патч профиля или строка плагина в интерфейсе): ```yaml - id: copilot-quota config: cacheMs: 300000 # кэш ответа GitHub, мс (0 — без кэша) ``` ## Как это работает | Половина | Файл | Ответственность | |---|---|---| | Серверная | `index.js` | Читает запись `llm-pi-ai/github-copilot` через `ctx.credentials`, опрашивает GitHub, отдаёт `GET /copilot-quota/api` | | Клиентская | `client.js` | Слот `conversation.input.right`; опрос раз в 2 минуты и при возврате фокуса в окно | Серверная половина обращается к тому же клиентскому эндпоинту, что и VS Code: ``` GET https://api.github.com/copilot_internal/user Authorization: Bearer ``` Поддерживаются обе структуры ответа: `quota_snapshots` (актуальная) и `monthly_quotas` + `limited_user_quotas` (старая). Ответ кэшируется на сервере (по умолчанию 5 минут), а при сбое обновления на экране остаётся последнее удачное значение. **Токены не попадают в браузер.** Грант остаётся в хранилище учётных данных харнесса, через маршрут проходят только числа. Бейдж обращается к тому же источнику, что отдал страницу (`/copilot-quota/api`). ## Проверка без интерфейса ```sh curl http://127.0.0.1:3080/copilot-quota/api ``` ## Ограничения - `copilot_internal/user` — не публичный API GitHub. Если структура ответа изменится, бейдж покажет ошибку в подсказке, а не сломает интерфейс. - GitHub Enterprise не поддерживается (белый список грантов в `dsh-oauth-copilot` принимает только официальный `proxy.individual.githubcopilot.com`). - Бейдж показывает квоту учётной записи, а не выбранной модели: он виден при любой модели. - Квота перезапрашивается по таймеру, поэтому число отстаёт от реального расхода на величину окна кэша. ## Лицензия MIT — см. [LICENSE](LICENSE). English version: [README.md](README.md).