@goodandready/dsh-cost-meter 0.8.2 → 0.8.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/client.js +241 -43
- package/lib/index.js +43 -1
- package/lib/updater.js +270 -0
- package/package.json +7 -4
- package/docs/README.ru.md +0 -162
- package/docs/README.zh.md +0 -150
- package/docs/deployment/public-release.md +0 -9
- package/docs/design/DESIGN.md +0 -117
- package/docs/plans/findings.md +0 -13
- package/docs/plans/progress.md +0 -12
- package/docs/plans/task_plan.md +0 -31
- package/docs/testing/projection-lifecycle.md +0 -28
- package/docs/testing/public-route.md +0 -12
package/docs/design/DESIGN.md
DELETED
|
@@ -1,117 +0,0 @@
|
|
|
1
|
-
# DESIGN.md — dsh-cost-meter
|
|
2
|
-
|
|
3
|
-
## Product / Purpose
|
|
4
|
-
- Назначение: Отображение стоимости активной сессии диалога в реальном времени, тарифов (пик / не-пик / единый) за 1M токенов, обратного отсчёта до смены окна, прозрачной детализации расходов по каждой задействованной модели и нативного управления конфигурацией плагина.
|
|
5
|
-
- Аудитория: Пользователи и инженеры DeepSeek Harness, контролирующие потребление токенов и бюджет на LLM-провайдеров.
|
|
6
|
-
- Статус: Активная публичная поставка (@goodandready/dsh-cost-meter).
|
|
7
|
-
|
|
8
|
-
## User Surfaces
|
|
9
|
-
- Web/UI:
|
|
10
|
-
- Компактный чип в слоте `conversation.session.header.utilities` (order: 10).
|
|
11
|
-
- Выпадающая панель детализации (width: 320px, absolute positioning, click-outside dismissal).
|
|
12
|
-
- Карточка настроек плагина в `settings.plugin.item` (слот `settings.plugin.item` с fallback на `settings.section`).
|
|
13
|
-
- DSH UI / settings / slots:
|
|
14
|
-
- Слот чипа: `conversation.session.header.utilities`.
|
|
15
|
-
- Слот карточки настроек: `settings.plugin.item`.
|
|
16
|
-
- Настройки: реестр DSH `settings.register("dsh-cost-meter", Config)` (валюта `currency`, множитель курса `usdRate`, таймзона `displayTimeZone`, опрос OpenRouter `useOpenRouter`, ручные ставки `prices`, сопоставление `modelMap`).
|
|
17
|
-
- Локализация: регистрация словарей через `ctx.locale.register("dsh-cost-meter", { en, ru })` с поддержкой переключения языков через `useActiveLocale(ctx)`.
|
|
18
|
-
- API:
|
|
19
|
-
- HTTP `GET /dsh-cost-meter/state` (параметр `?models=...` для получения тарифов по задействованным моделям).
|
|
20
|
-
- CLI:
|
|
21
|
-
- Управление через CLI харнесса: `dsh plugin --profile web add @goodandready/dsh-cost-meter`.
|
|
22
|
-
- Документация:
|
|
23
|
-
- README.md, index.md, docs/testing/public-route.md, docs/testing/projection-lifecycle.md, docs/deployment/public-release.md.
|
|
24
|
-
|
|
25
|
-
## Visual Direction (Unified with dsh-clinebot)
|
|
26
|
-
- Атмосфера: Строгий утилитарный нативный интерфейс DSH, высокая информационная плотность без визуального шума.
|
|
27
|
-
- Утверждённые референсы: Эталонный плагин `@goodandready/dsh-clinebot`, дизайн-система DeepSeek Harness (`--dsw-alias-*`), карточки секций `.dcm-section-card`, бейджи статуса `.dcm-badge`, адаптивная сетка параметров `.dcm-grid-2`, чипы в шапке сессии.
|
|
28
|
-
- Отказоустойчивость: Обязательный `ErrorBoundary` вокруг карточки настроек и поповера шапки (предотвращает исчезновение слотов ядра при исключениях рендеринга).
|
|
29
|
-
- Синхронизация зеркал: `refreshMirrorUntilVisible(ctx)` для надёжного доступа к зеркалу `settingsScope`.
|
|
30
|
-
- Атмосфера: Строгий утилитарный нативный интерфейс DSH, высокая информационная плотность без визуального шума.
|
|
31
|
-
- Утверждённые референсы: Дизайн-система DeepSeek Harness (`--dsw-alias-*`), чипы в шапке сессии (`dsh-key-rotation`, `dsh-context-lens`), стандарт карточек настроек DSH.
|
|
32
|
-
- Не копировать: Избыточные градиенты, внешние модальные окна, тяжелые тени, кастомные несогласованные шрифты.
|
|
33
|
-
|
|
34
|
-
## Foundations
|
|
35
|
-
- Цвета и роли:
|
|
36
|
-
- `--dsw-alias-label-primary`: основной текст, заголовки, суммы.
|
|
37
|
-
- `--dsw-alias-label-tertiary`: второстепенные пояснения, метки столбцов, чип без тарифа.
|
|
38
|
-
- `--dsw-alias-border-l2`: разделители секций и обводка панели.
|
|
39
|
-
- `--dsw-alias-bg-layer-2` / `--dsw-alias-bg-base`: подложка всплывающей панели и карточки настроек.
|
|
40
|
-
- `--dsw-alias-state-success-primary` / `--dsw-alias-state-success-tertiary`: подсветка льготного окна (не-пик).
|
|
41
|
-
- `--dsw-alias-state-warn-primary` / `--dsw-alias-state-warn-tertiary`: подсветка полного тарифа (пик).
|
|
42
|
-
- Типографика:
|
|
43
|
-
- Системный стек шрифтов DSH, размер 12px, интерлиньяж 1.5.
|
|
44
|
-
- Обязательно `fontVariantNumeric: "tabular-nums"` для всех числовых колонок, токенов и таймеров.
|
|
45
|
-
- Сетка и отступы:
|
|
46
|
-
- Чип: высота 22px, padding: 0 8px, gap: 6px, border-radius: 6px.
|
|
47
|
-
- Панель: padding: 12px 14px, border-radius: 10px, ширина 320px.
|
|
48
|
-
- Карточка настроек: нативный складной контейнер (`.dcm-card`) с шапкой, статусами-бейджами (`dcm-badge-ok`, `dcm-badge-warn`, `dcm-badge-bad`), 3 структурированными секциями (`Основные параметры`, `Каталог OpenRouter`, `Диагностика и статус`), защитой ввода и кнопкой сохранения (`dcm-btn-primary`).
|
|
49
|
-
|
|
50
|
-
## Components & States
|
|
51
|
-
- Чип:
|
|
52
|
-
- `Unknown Tariff`: отображает «тариф ?» в приглушённом цвете `label-tertiary`.
|
|
53
|
-
- `Flat Tariff`: фон `--dsw-alias-state-warn-tertiary`, текст `--dsw-alias-state-warn-primary`, заголовок «Единый тариф».
|
|
54
|
-
- `Off-Peak`: зелёная плашка успеха (льготный тариф).
|
|
55
|
-
- `Peak`: оранжевая плашка предупреждения (полный тариф).
|
|
56
|
-
- Таймер: время до смены тарифа с пониженной непрозрачностью (`opacity: 0.75`).
|
|
57
|
-
- Панель:
|
|
58
|
-
- Заголовок с текущей моделью и статусом окна.
|
|
59
|
-
- Сетка тарифов за 1M токенов (не-пик / пик / единая ставка).
|
|
60
|
-
- Блок «Из чего сложилась сумма»:
|
|
61
|
-
- Список всех моделей сессии с токенами и суммарной стоимостью.
|
|
62
|
-
- Для модели без тарифа отображается статус `не указана стоимость` (`rate_unspecified`).
|
|
63
|
-
- Итог сессии: `Сессия: ≈ <валюта><сумма>`.
|
|
64
|
-
- Отсутствие мусорных служебных плашек (строка источника OpenRouter исключена).
|
|
65
|
-
- Карточка настроек (`CostMeterCard`):
|
|
66
|
-
- Сворачиваемый заголовок с шевроном и иконкой счётчика.
|
|
67
|
-
- Статус снимка: `ready` (зелёный бейдж), `loading` (нейтральный), `unavailable` (серый).
|
|
68
|
-
- Поля: выбор символа валюты (`currency`), курс к USD (`usdRate`), таймзона отображения (`displayTimeZone`).
|
|
69
|
-
- Локализованные лейблы и плейсхолдеры на русском и английском языках.
|
|
70
|
-
|
|
71
|
-
## User Flows
|
|
72
|
-
1. Пользователь ведёт диалог с ассистентом: чип в шапке инкрементально обновляет потраченную сумму прямо во время стриминга ответа ассистента.
|
|
73
|
-
2. Пользователь нажимает на чип: открывается всплывающая панель с тарифной сеткой и расходами по каждой модели сессии.
|
|
74
|
-
3. Если модель не тарифицирована: в списке моделей выводится статус `не указана стоимость`.
|
|
75
|
-
4. Пользователь открывает настройки DSH (`Настройки` -> `Плагины`): карточка `dsh-cost-meter` позволяет изменить валюту, курс и таймзону с мгновенным сохранением в `settingsScope`.
|
|
76
|
-
|
|
77
|
-
## Do / Don't
|
|
78
|
-
- Do:
|
|
79
|
-
- Использовать CSS-переменные DSH для согласованности с тёмной и светлой темами.
|
|
80
|
-
- Всегда разделять расходы по задействованным моделям.
|
|
81
|
-
- Использовать табличные цифры (`tabular-nums`) для предотвращения дёргания вёрстки при стриме.
|
|
82
|
-
- Использовать `ctx.locale.register` и `useActiveLocale` для всех строк интерфейса.
|
|
83
|
-
- Don't:
|
|
84
|
-
- Не выводить техническую служебную информацию о каталоге OpenRouter в интерфейс пользователя.
|
|
85
|
-
- Не заменять отсутствие тарифа обманчивым нулём или невнятным прочерком — писать прямо `не указана стоимость`.
|
|
86
|
-
- Не допускать утечек локальных путей и инфраструктурных данных в коде или документации.
|
|
87
|
-
|
|
88
|
-
## History & Decisions
|
|
89
|
-
- 2026-09-13 (v0.8.2):
|
|
90
|
-
- Приведение к стандарту локализации DSH (dsh-plugin-authoring): английский (en) — исходный и fallback-язык, китайский (zh) — обязательная пользовательская локаль. Русский словарь вынесен из плагина; все строки для русского интерфейса переданы в goodandready/dsh-russian-lang.
|
|
91
|
-
- Нативный точечный dot-индикатор статуса чипа в шапке (.dcm-dot): зеленый (off-peak), янтарный (peak), красный пульсирующий (budget exceeded), серый (idle/unknown).
|
|
92
|
-
- Адаптивное скрытие таймера чипа на экранах < 680px при сохранении суммы расхода.
|
|
93
|
-
- Расчёт и отображение выгоды от контекстного кэша (Cache Savings): строка 'Cache saved: ≈ $X.XX (-Y%)' при наличии cacheReadTokens.
|
|
94
|
-
- Компактный список моделей с аккордеоном при 3+ задействованных моделях сессии.
|
|
95
|
-
- 2026-09-12 (v0.8.1):
|
|
96
|
-
- Оптимизация производительности расчёта тарифов: замена 1440-минутного цикла на алгоритм O(K) по точкам перехода и мемоизация экстремумов через WeakMap.
|
|
97
|
-
- Серверный кэш разрешения тарифов resolveTariffCache (Map) с автоматической очисткой при обновлении каталога.
|
|
98
|
-
- Поддержка ETag и ответа 304 Not Modified на эндпоинте /dsh-cost-meter/state.
|
|
99
|
-
- Кнопка ручной синхронизации каталога цен в секции OpenRouter с защитой от флуда (cooldown 30 сек).
|
|
100
|
-
- Интеллектуальные подсказки экономии: плашка скорого наступления льготного тарифа (скидка 50%) и отсчёт времени.
|
|
101
|
-
- Поддержка настраиваемого порога бюджета сессии (budgetThreshold) с предупреждающей подсветкой чипа.
|
|
102
|
-
- Кнопка быстрого копирования текстового отчёта о расходах в буфер обмена.
|
|
103
|
-
- Таблица нормализации алиасов вендоров (z-ai -> zai, deepseek-official -> deepseek, gemini -> google).
|
|
104
|
-
- 2026-09-05 (v0.7.9):
|
|
105
|
-
- Hotfix: исправлен ReferenceError (t is not defined) в объекте словаря ru (lib/client.js) (#15).
|
|
106
|
-
- Добавлен автоматический тест на чистое исполнение фабрики client loader (`test/public-route.test.mjs`).
|
|
107
|
-
- 2026-09-05 (v0.7.4):
|
|
108
|
-
- Добавлена нативная карточка настроек в слот `settings.plugin.item` (`#12`).
|
|
109
|
-
- Реализована полная локализация клиентской части через `ctx.locale.register` (`#2`).
|
|
110
|
-
- Реализовано provider-aware разрешение тарифов OpenRouter vs DeepSeek (`#3`).
|
|
111
|
-
- Добавлены всеобъемлющие регрессионные тесты на проекцию и сопоставление (`test/projection-lifecycle.test.mjs`, `#1`).
|
|
112
|
-
- Закрыт issue о согласовании публичного scope пакета (`#13`).
|
|
113
|
-
- 2026-09-05 (v0.7.3):
|
|
114
|
-
- Удалена строка источника цен OpenRouter.
|
|
115
|
-
- Список моделей в блоке «Из чего сложилась сумма» унифицирован и отображается для всех задействованных моделей сессии.
|
|
116
|
-
- Для нетарифицированных моделей введён явный статус «не указана стоимость».
|
|
117
|
-
- Пакет переведён на публичный scope `@goodandready/dsh-cost-meter`.
|
package/docs/plans/findings.md
DELETED
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
# Findings: Issue #27 (v0.8.2)
|
|
2
|
-
|
|
3
|
-
## 1. Точечный индикатор статуса
|
|
4
|
-
- Сплошной яркий фон чипа в тулбаре DSH перетягивает на себя внимание от основного чата.
|
|
5
|
-
- Нативный паттерн DSH: нейтральный полупрозрачный фон с цветной точкой (dot indicator 6x6px) и моноширинным текстом `tabular-nums`.
|
|
6
|
-
|
|
7
|
-
## 2. Экономия кэша (Cache Savings)
|
|
8
|
-
- При использовании кэша провайдера (DeepSeek, Claude, Gemini) стоимость `cacheReadTokens` значительно ниже `uncachedInputTokens` (у DeepSeek: $0.014 vs $0.14-$0.44 за 1M токенов).
|
|
9
|
-
- Разница между стоимостью токенов без кэша (`cacheReadTokens * inputRate`) и фактической стоимостью (`cacheReadTokens * cacheHitRate`) наглядно демонстрирует реальную экономию пользователя прямо в поповере.
|
|
10
|
-
|
|
11
|
-
## 3. Стандарт локализации
|
|
12
|
-
- По стандарту DSH (`dsh-plugin-authoring`, `dhs-plugin-release-workflow`), плагин обязан иметь `en` как канонический исходный и `zh` как обязательную локаль.
|
|
13
|
-
- Русский перевод не зашивается в плагин, а поставляется через отдельный плагин `dsh-russian-lang`. Для синхронизации перевода открывается issue в репозитории `goodandready/dsh-russian-lang`.
|
package/docs/plans/progress.md
DELETED
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
# Progress: Issue #27 (v0.8.2)
|
|
2
|
-
|
|
3
|
-
- **2026-09-13 15:06**:
|
|
4
|
-
- Создана Gitea Issue #27.
|
|
5
|
-
- Развернут worktree `.worktrees/issue-27` на ветке `feat/issue-27-ui-and-locales`.
|
|
6
|
-
- Зафиксированы планы и стандарты в `docs/plans/`.
|
|
7
|
-
|
|
8
|
-
- **2026-09-13 15:08**:
|
|
9
|
-
- Реализованы улучшения в `lib/client.js` (dot status indicator, cache savings display, multi-model accordion, en/zh locales).
|
|
10
|
-
- Добавлены тесты в `test/v082-ui-locales.test.mjs` (все 22 теста успешно пройдены).
|
|
11
|
-
- Версия обновлена до `0.8.2`.
|
|
12
|
-
- Документация актуализирована на en, zh, ru.
|
package/docs/plans/task_plan.md
DELETED
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
# Task Plan: Issue #27 (v0.8.2) — Визуальная индикация шапки/поповера и стандарт локализации en/zh
|
|
2
|
-
|
|
3
|
-
## Цели
|
|
4
|
-
1. **Визуальные улучшения шапки и поповера**:
|
|
5
|
-
- Чип в шапке: точечный dot-индикатор (зеленый/янтарный/красный/серый) вместо сплошного фона, аккуратная интеграция с тулбаром DSH.
|
|
6
|
-
- Адаптивное скрытие таймера на узких экранах, сохранение суммы.
|
|
7
|
-
- Индикация экономии контекстного кэша (Cache Savings): строка `Cache saved: ≈ $X.XX (-Y%)`.
|
|
8
|
-
- Компактный список/аккордеон при нескольких моделях сессии (3+ модели).
|
|
9
|
-
- Точные нативные токены тем DSH.
|
|
10
|
-
2. **Стандарт локализации DSH**:
|
|
11
|
-
- Исходный и fallback язык: `en`.
|
|
12
|
-
- Обязательная локаль: `zh` (полный набор эквивалентных ключей).
|
|
13
|
-
- Исключение зашитого `ru` словаря из плагина.
|
|
14
|
-
- Создание Issue в `goodandready/dsh-russian-lang` со всеми строками для русского перевода.
|
|
15
|
-
3. **Документация и релиз**:
|
|
16
|
-
- Версия `0.8.2` (инкремент только `z`).
|
|
17
|
-
- Актуализация `docs/design/DESIGN.md`, `README.md` (en), `docs/README.zh.md` (zh), `docs/README.ru.md` (ru).
|
|
18
|
-
- 100% покрытие unit-тестами без внешних зависимостей.
|
|
19
|
-
- Валидация на test server (`:3082`) и на production (`:3080`).
|
|
20
|
-
- Запрос подтверждения -> публикация v0.8.2.
|
|
21
|
-
|
|
22
|
-
## Статус выполнения
|
|
23
|
-
- [x] Issue #27 создана
|
|
24
|
-
- [x] Worktree `.worktrees/issue-27` развернут
|
|
25
|
-
- [x] Реализация `lib/client.js` (UI шапки/поповера, расчет cache savings, словари en/zh)
|
|
26
|
-
- [x] Обновление тестов в `test/`
|
|
27
|
-
- [x] Обновление документации (`DESIGN.md`, `README.md`, `README.zh.md`, `README.ru.md`)
|
|
28
|
-
- [ ] Регистрация Issue в `goodandready/dsh-russian-lang`
|
|
29
|
-
- [ ] Сборка и приёмка кандидата (:3082, :3080)
|
|
30
|
-
- [ ] Публикация релиза v0.8.2
|
|
31
|
-
- [ ] Закрытие Issue #27 и cleanup worktree
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
# Регрессионное тестирование проекции тарифов и жизненного цикла
|
|
2
|
-
|
|
3
|
-
Тесты проверяют логику тарификации, парсинг временных окон UTC, сопоставление моделей и provider-aware разрешение ставок.
|
|
4
|
-
|
|
5
|
-
## Запуск тестов
|
|
6
|
-
|
|
7
|
-
```bash
|
|
8
|
-
npm test
|
|
9
|
-
```
|
|
10
|
-
|
|
11
|
-
## Проверяемые сценарии (`test/projection-lifecycle.test.mjs`)
|
|
12
|
-
|
|
13
|
-
1. **`hhmmToMinutes` и `parseWindow`**:
|
|
14
|
-
- Корректный разбор диапазонов `HH:MM-HH:MM` в минуты от начала суток UTC.
|
|
15
|
-
- Граничные условия: переход через полночь (`23:00-02:00`), пустые или невалидные строки.
|
|
16
|
-
|
|
17
|
-
2. **`slotOf`**:
|
|
18
|
-
- Вычисление 30-минутного слота суток (`0..47`) на основе переданного timestamp.
|
|
19
|
-
- Независимость накопления расхода от текущего момента времени (сохранение исторической ставки слота).
|
|
20
|
-
|
|
21
|
-
3. **`indexCatalog` и `matchModel`**:
|
|
22
|
-
- Индексация моделей OpenRouter с поддержкой поиска без учета регистра.
|
|
23
|
-
- Нормализация суффиксов вендоров и версий (например, `vendor/model:variant`).
|
|
24
|
-
|
|
25
|
-
4. **`resolveTariff` (Provider-aware)**:
|
|
26
|
-
- Если указан `provider: "openrouter"`, плагин в первую очередь обращается к каталогу OpenRouter, даже если имя модели содержит `deepseek`.
|
|
27
|
-
- Если провайдер не `openrouter` (или `deepseek`), DeepSeek модели тарифицируются по официальной зашитой сетке (пик / не-пик).
|
|
28
|
-
- Ручные ставки `prices` из конфигурации имеют высший приоритет над внешними каталогами.
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
# Проверка публичного маршрута
|
|
2
|
-
|
|
3
|
-
1. Выполнить `npm test`.
|
|
4
|
-
2. Проверить `npm pack --dry-run` и отсутствие локальных установочных ссылок,
|
|
5
|
-
абсолютных infra-путей, IP-адресов и секретов в поставляемых файлах.
|
|
6
|
-
3. Собрать tarball из проверенного Git worktree.
|
|
7
|
-
4. Установить tarball на изолированный тестовый DSH web server (MiniPC).
|
|
8
|
-
5. Для browser half проверить loader id `@goodandready/dsh-cost-meter`, HTTP route
|
|
9
|
-
состояния `GET /dsh-cost-meter/state` и smoke-сценарий тарификации (список моделей,
|
|
10
|
-
расчёт стоимости, статус «не указана стоимость»); для host half — bundle identity и host smoke.
|
|
11
|
-
6. Выполнить cleanup тестовой установки и убедиться, что постоянные плагины
|
|
12
|
-
сохранили работоспособность.
|