Skip to content

feat: аналитика токенов — разбивка стоимости, сравнение подписок, поддержка OpenCode#17

Closed
NovakPAai wants to merge 1 commit into
vakovalskii:mainfrom
NovakPAai:feat/token-analytics-contribution
Closed

feat: аналитика токенов — разбивка стоимости, сравнение подписок, поддержка OpenCode#17
NovakPAai wants to merge 1 commit into
vakovalskii:mainfrom
NovakPAai:feat/token-analytics-contribution

Conversation

@NovakPAai
Copy link
Copy Markdown
Collaborator

@NovakPAai NovakPAai commented Apr 6, 2026

feat: аналитика токенов — разбивка стоимости, сравнение подписок, поддержка OpenCode

Что сделано

  • Разбивка по типам токенов (input/output/cache_read/cache_write) с процентами во вкладке Cost Analytics
  • Метрика утилизации контекстного окна (средний % по всем ходам, база 200K)
  • Мультипериодное сравнение подписки vs API с ROI и прогресс-баром
  • Диаграмма стоимости по агентам с индикаторами качества данных
  • Поддержка реальных данных OpenCode через batch-запрос к SQLite
  • Защита от SQL-инъекций для OpenCode session ID
  • Бейджи прозрачности данных (реальные ✓ / оценка ~est. / нет данных ✗)

Что изменилось

src/data.js (+183 строки)

computeSessionCost() — расширенная сигнатура возврата:

{ cost, inputTokens, outputTokens, cacheReadTokens, cacheCreateTokens, contextPctSum, contextTurnCount, model }
  • Кэш-токены теперь трекаются отдельно (раньше входили в input)
  • Context % считается per-turn (раньше — пик за сессию)
  • Новая ветка OpenCode: запрос к SQLite за tokens.input/output, tokens.cache.read/write
  • Session ID валидируется через /^[a-zA-Z0-9_-]+$/ перед shell-выполнением

getCostAnalytics() — новые поля агрегации:

  • totalInputTokens, totalOutputTokens, totalCacheReadTokens, totalCacheCreateTokens
  • avgContextPct, dailyRate, firstDate, lastDate, days
  • byAgent (стоимость/сессии/токены/estimated по каждому агенту), agentNoCostData
  • sessionsWithData заменяет sessions.length для totalSessions
  • Batch pre-computation для OpenCode: один execSync на все сессии вместо O(n)

src/frontend/app.js (+193 строки)

  • Детали сессии: кэш-токены отображаются рядом с input/output
  • Система подписок: getSubscriptionConfig() с миграцией из старого формата {plan, paid} → новый {entries: [{plan, paid, from}]}; addSubEntry() / removeSubEntry() с сортировкой по дате
  • renderAnalytics(): сетка токенов, карточки сравнения подписок + управление периодами, бейджи покрытия, диаграмма "Cost by Agent"
  • Бейдж OpenCode: ✓ (реальные данные) или ~est. (нет модели) или ✗ (нет токенов)

src/frontend/styles.css (+200 строк)

  • Сетка и карточки для разбивки токенов
  • Карточки сравнения подписок, прогресс-бар, список периодов
  • Индикаторы покрытия (.coverage-ok, .coverage-est, .coverage-none)
  • Адаптивные инпуты для формы добавления периодов подписки

Как это работает

Разбивка токенов

Каждое assistant-сообщение в Claude Code JSONL содержит usage.input_tokens, usage.output_tokens, usage.cache_creation_input_tokens, usage.cache_read_input_tokens. Теперь они трекаются раздельно и отображаются в виде сетки из 5 карточек с процентами.

Токены OpenCode

loadOpenCodeDetail() уже читает msgData.tokens из SQLite, но не использует для расчёта стоимости. Новый код читает tokens.input, tokens.output, tokens.reasoning, tokens.cache.read, tokens.cache.write и применяет ценообразование через msgData.modelID.

Для аналитики один batch-запрос выбирает ВСЕ assistant-сообщения OpenCode разом:

SELECT session_id, data FROM message
WHERE json_extract(data, '$.role') = 'assistant' ORDER BY time_created

Результаты кэшируются в opencodeCostCache и переиспользуются в основном цикле.

Сравнение с подпиской

Пользователь добавляет периоды оплаты через localStorage (codedash-subscription):

{ "entries": [{ "plan": "Pro", "paid": 20, "from": "2025-01-01" }, { "plan": "Max", "paid": 100, "from": "2025-03-01" }] }

UI показывает: сумму оплаченного vs API-эквивалент, экономию/переплату, множитель ROI, прогресс-бар.

Контекстное окно

avgContextPct = sum(per-turn context%) / turnCount, где per-turn context = input + cache_create + cache_read как процент от 200K.

Ограничения

  • Cursor/Kiro: данные о токенах в их форматах хранения отсутствуют
  • Codex: только оценка по размеру файла, помечена как ~est.
  • OpenCode без modelID: фоллбэк на дефолтный прайсинг, помечен как ~est.
  • Контекстное окно захардкожено на 200K (все модели Claude)
  • Фильтрация подписок по датам не реализована (итого = сумма всех периодов)
  • Доработка тем dark/monokai не требуется (наследует существующие CSS-переменные)

Тест-план

  • Запустить node bin/cli.js run --port=3333, убедиться что вкладка Cost Analytics загружается
  • Проверить что разбивка токенов показывает корректные проценты (сумма = 100%)
  • Добавить период подписки, проверить сохранение после перезагрузки страницы
  • Удалить период подписки, проверить обновление UI
  • Проверить соответствие бейджей покрытия установленным агентам
  • Тест с установленным OpenCode: реальные счётчики токенов появляются
  • Тест без OpenCode: нет ошибок, OpenCode отсутствует или показывает ✗
  • Проверить что в деталях сессии отображаются кэш-токены (если есть)
  • Проверить что диаграмма "Cost by Agent" появляется только при 2+ агентах с данными
  • Убедиться в отсутствии ошибок в консоли браузера (DevTools)

Closes #18

…Code support

Add comprehensive cost analytics to the dashboard:
- Token type breakdown (input/output/cache_read/cache_write)
- Context window utilization percentage (avg across all turns)
- Multi-period subscription vs API cost comparison with ROI
- Per-agent cost breakdown chart
- Data coverage transparency (which agents have real/estimated/no data)
- OpenCode real token data support via SQLite batch query
- SQL injection protection for OpenCode session IDs
- Daily spend rate calculation

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@NovakPAai NovakPAai changed the title feat: token analytics — cost breakdown, subscription comparison, OpenCode support feat: аналитика токенов — разбивка стоимости, сравнение подписок, поддержка OpenCode Apr 6, 2026
@vakovalskii
Copy link
Copy Markdown
Owner

Closing — tracked as issue #18. The analytics overhaul is a good idea but needs to be done incrementally. Current PR conflicts with recent performance changes in data.js.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Аналитика токенов — разбивка стоимости, сравнение подписок, поддержка OpenCode

2 participants