README со скриншотом панели
Что показывает вкладка «Токены», как устроен прокси внутри OpenCode, установка без обёртки, переменные окружения, запуск server.mjs отдельно под Node.
This commit is contained in:
@@ -0,0 +1,123 @@
|
||||
# context-panel
|
||||
|
||||
Панель «Токены» для веб-интерфейса OpenCode 2: что сейчас лежит в контексте сессии, как он рос и сколько
|
||||
токенов ушло за сессию, за день и за всё время. Работает как плагин OpenCode и поднимается в его же процессе.
|
||||
|
||||
<img src="docs/panel.png" alt="Вкладка «Токены» в боковой панели OpenCode" width="600">
|
||||
|
||||
## Что на вкладке
|
||||
|
||||
В шапке сессии появляется кнопка с кружком и % заполнения контекста. Она открывает боковую панель на вкладке
|
||||
**«Токены»** рядом с Review и Context; вкладку можно выбрать и вручную. Кнопка и вкладка повторяют разметку
|
||||
OpenCode, поэтому стили у них родные. Если OpenCode перерисует интерфейс, `panel.js` вставит их заново.
|
||||
|
||||
- **Состав контекста.** Сколько токенов было в последнем запросе к модели (как в самом OpenCode) из лимита
|
||||
модели. Разбивка по категориям: сообщения, ответы, reasoning, вывод каждого тула (MCP отдельно,
|
||||
`gitlab: …`, `jira: …`; для Code Mode — какие MCP вызывал скрипт), сводка compaction. Учитывается только
|
||||
то, что сейчас в контексте, — его отдаёт сам OpenCode (`/api/session/{id}/context`). Категории считаются как
|
||||
символы/4, так же оценивает сам OpenCode. «Остаток» — это разница между реальным числом токенов и суммой
|
||||
оценок: системный промпт, AGENTS.md, схемы тулов и MCP, плюс погрешность.
|
||||
- **Рост контекста по шагам.** Токенов в каждом запросе к модели за всю сессию, линия лимита модели и отметки
|
||||
compaction. Под графиком — список compaction: когда, авто или вручную, контекст до и после, размер сводки,
|
||||
сколько заняло. Провал на графике без отметки compaction — это чистка вывода тулов (prune / DCP).
|
||||
- **Самые тяжёлые вызовы в контексте.** Топ-10 вызовов тулов в текущем контексте: тул, что вызывали (файл,
|
||||
команда, описание), токены входа и вывода.
|
||||
- **Расход за сессию.** Input, cache read/write, output, reasoning, число шагов модели. Если были сабагенты,
|
||||
рядом показан итог вместе с ними.
|
||||
- **Скорость модели в сессии.** Генерация (output + reasoning за время потока, ток/с), среднее ожидание первого
|
||||
токена, prefill (input без кэша за это время, ток/с) и среднее время модели на шаг. Начало потока — первая
|
||||
часть ответа, конец — `time.streamed` сообщения. Выполнение тулов не считается.
|
||||
- **Расход за сегодня / 7 дней / 30 дней / всё время**, по проекту или по всем проектам, плюс топ моделей
|
||||
(со скоростью генерации и временем на шаг). Над таблицей — график с выбором периода: сегодня по часам, 7 и
|
||||
30 дней по дням, всё время по дням или по неделям, если история длиннее 90 дней. Столбики разбиты по типу
|
||||
токенов (Cache / Input / Output) или по моделям (топ-4 + «другие»).
|
||||
|
||||
Каждый раздел сворачивается кликом по заголовку; какие свёрнуты — запоминается в браузере (`localStorage`).
|
||||
Данные обновляются раз в 3 секунды, пока вкладка выбрана, % на кнопке — раз в 10 секунд.
|
||||
|
||||
## Как устроено
|
||||
|
||||
У веб-интерфейса OpenCode нет точек расширения: он зашит в бинарник, слоты для плагинов есть только в TUI, а
|
||||
своих HTTP-маршрутов серверный плагин добавить не может. Поэтому плагин `context-panel.v2.ts` поднимает внутри
|
||||
процесса OpenCode прокси (`server.mjs`) на отдельном порту. Прокси пропускает HTTP, SSE и WebSocket как есть, а
|
||||
в HTML-страницы вставляет `<script src="/__ctx/panel.js">`. CSP страницы (`script-src 'self'`) скрипт
|
||||
пропускает: он с того же origin. Service worker веб-интерфейса прокси подменяет «гасящим», иначе тот отдавал бы
|
||||
страницу из кэша без панели.
|
||||
|
||||
```
|
||||
браузер → :4196 server.mjs (в процессе OpenCode) ─┬─ /__ctx/panel.js, /__ctx/api/* → opencode.db (только чтение) + API OpenCode
|
||||
└─ всё остальное → :4197 opencode serve
|
||||
```
|
||||
|
||||
`/__ctx/*` закрыт тем же паролем, что и сам OpenCode: прокси сверяет заголовок `Authorization` с OpenCode и с
|
||||
ним же берёт из API лимит модели и текущий контекст сессии. Зависимостей нет: в OpenCode база читается через
|
||||
`bun:sqlite`, под Node ≥ 22.5 — через `node:sqlite`.
|
||||
|
||||
Особенности плагинов OpenCode 2 (проверено на 2.1.3):
|
||||
|
||||
- **Плагин грузится лениво** — при первом запросе к API проекта, а не при старте `opencode serve`. Пока такого
|
||||
запроса не было, порт панели пуст. Поэтому после старта нужно один раз дёрнуть API (см. «Установка»).
|
||||
- **Модуль импортируется заново для каждого проекта.** Прокси один на процесс (флаг в `globalThis`).
|
||||
- **При выгрузке проекта прокси не закрывается.** Браузер ходит через него, и без прокси OpenCode не получил
|
||||
бы запрос, который загрузит плагин снова. Живёт, пока жив процесс.
|
||||
|
||||
## Установка
|
||||
|
||||
1. Положить ссылку на плагин в `plugins/` конфига OpenCode (в `"plugin"` в `opencode.jsonc` не добавлять:
|
||||
имя там считается npm-пакетом). `server.mjs` и `panel.js` плагин ищет рядом с настоящим файлом:
|
||||
|
||||
```bash
|
||||
ln -sfn "$PWD/context-panel.v2.ts" "${XDG_CONFIG_HOME:-$HOME/.config}/opencode/plugins/"
|
||||
```
|
||||
|
||||
2. Запустить OpenCode на соседнем порту и сказать плагину, где слушать:
|
||||
|
||||
```bash
|
||||
CTX_PANEL_LISTEN=4196 CTX_PANEL_TARGET=4197 opencode serve --hostname 127.0.0.1 --port 4197
|
||||
```
|
||||
|
||||
3. Загрузить плагин первым запросом к API и открыть `http://127.0.0.1:4196/` (на 4197 панели нет):
|
||||
|
||||
```bash
|
||||
curl -s -o /dev/null -u opencode:"$OPENCODE_SERVER_PASSWORD" http://127.0.0.1:4197/api/plugin
|
||||
```
|
||||
|
||||
Переменные окружения плагина:
|
||||
|
||||
| Переменная | По умолчанию | Что |
|
||||
| --- | --- | --- |
|
||||
| `CTX_PANEL_LISTEN` | `4196` | порт прокси с панелью |
|
||||
| `CTX_PANEL_TARGET` | `4197` | порт самого `opencode serve` |
|
||||
| `CTX_PANEL_DB` | `$XDG_DATA_HOME/opencode/opencode.db` | база OpenCode |
|
||||
| `OPENCODE_CONTEXT_PANEL` | — | `0` — не запускать |
|
||||
|
||||
Журнал плагина: `$XDG_DATA_HOME/opencode/log/context-panel.log` (на каком порту поднялся или почему нет).
|
||||
|
||||
В mms-challenge всё это делает обёртка `egress-filter/bin/opencode-web` (`make opencode`): кладёт ссылку,
|
||||
передаёт порты, после старта дёргает API, ждёт порт 4196 и только потом открывает браузер. Выключить панель:
|
||||
`OPENCODE_CONTEXT_PANEL=0 make opencode`.
|
||||
|
||||
### Без плагина
|
||||
|
||||
Тот же `server.mjs` можно запустить отдельным процессом под Node перед уже запущенным OpenCode:
|
||||
|
||||
```bash
|
||||
node --disable-warning=ExperimentalWarning server.mjs --listen 4196 --target 4197 \
|
||||
--db "${XDG_DATA_HOME:-$HOME/.local/share}/opencode/opencode.db"
|
||||
```
|
||||
|
||||
### Проверка
|
||||
|
||||
```bash
|
||||
curl -s -u opencode:"$OPENCODE_SERVER_PASSWORD" http://127.0.0.1:4196/ -H 'accept: text/html' | grep -c __ctx/panel.js
|
||||
```
|
||||
|
||||
Должно вывести `1`. Если панели нет — смотреть `context-panel.log` и консоль браузера. Если открыта старая
|
||||
вкладка, её нужно перезагрузить.
|
||||
|
||||
## Разработка
|
||||
|
||||
- Правки в `panel.js` применяются после перезагрузки страницы, правки в `server.mjs` и `context-panel.v2.ts` —
|
||||
после перезапуска OpenCode.
|
||||
- Панель читает внутреннюю схему `opencode.db` (таблицы `session_v2`, `session_message`). Если после обновления
|
||||
OpenCode она перестанет показывать данные, смотреть надо в `sessionStatsV2` / `globalRowsV2` в `server.mjs`.
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 254 KiB |
Reference in New Issue
Block a user