@goodandready/dsh-cost-meter 0.7.9 → 0.8.1
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/README.md +7 -0
- package/docs/README.ru.md +6 -0
- package/docs/design/DESIGN.md +15 -2
- package/docs/plans/findings.md +14 -19
- package/docs/plans/progress.md +11 -16
- package/docs/plans/task_plan.md +29 -30
- package/lib/client.js +693 -349
- package/lib/index.js +612 -522
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -138,3 +138,10 @@ npm test
|
|
|
138
138
|
## 📄 License
|
|
139
139
|
|
|
140
140
|
MIT © [GooDAnDReaDY](https://github.com/GooDAnDReaDY)
|
|
141
|
+
|
|
142
|
+
### Performance & Smart Cost Features (v0.8.1)
|
|
143
|
+
- **O(K) Rate Change Calculation**: Next schedule transition is resolved in $O(K)$ boundary hops instead of full-day iterations.
|
|
144
|
+
- **Server Cache & ETag**: High-throughput state polling with `304 Not Modified` support and internal tariff LRU cache.
|
|
145
|
+
- **Manual Catalog Sync**: On-demand catalog fetch via `POST /dsh-cost-meter/refresh` or UI "Sync Now" button.
|
|
146
|
+
- **Savings Advice & Budget Threshold**: Popover hints on impending off-peak discounts (50% off) and optional warning thresholds (`budgetThreshold`).
|
|
147
|
+
- **Quick Summary Export**: Instant markdown/text summary copy to clipboard.
|
package/docs/README.ru.md
CHANGED
|
@@ -138,3 +138,9 @@ npm test
|
|
|
138
138
|
## 📄 Лицензия
|
|
139
139
|
|
|
140
140
|
MIT © [GooDAnDReaDY](https://github.com/GooDAnDReaDY)
|
|
141
|
+
|
|
142
|
+
### Производительность и интеллектуальные подсказки (v0.8.1)
|
|
143
|
+
- **Алгоритм O(K)**: Моментальный расчёт границ смены тарифов и мемоизация экстремумов без лишних циклов в браузере.
|
|
144
|
+
- **Серверный кэш и ETag**: Поддержка заголовка `304 Not Modified` для маршрута `/state` и кэширование сопоставлений моделей.
|
|
145
|
+
- **Ручная синхронизация**: Кнопка «Синхронизировать сейчас» в настройках с защитой от флуда (`POST /dsh-cost-meter/refresh`).
|
|
146
|
+
- **Подсказки экономии и порог бюджета**: Отсчёт времени до льготного окна (скидка 50%), порог сессии (`budgetThreshold`) и экспорт сводки в буфер обмена.
|
package/docs/design/DESIGN.md
CHANGED
|
@@ -22,7 +22,11 @@
|
|
|
22
22
|
- Документация:
|
|
23
23
|
- README.md, index.md, docs/testing/public-route.md, docs/testing/projection-lifecycle.md, docs/deployment/public-release.md.
|
|
24
24
|
|
|
25
|
-
## Visual Direction
|
|
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`.
|
|
26
30
|
- Атмосфера: Строгий утилитарный нативный интерфейс DSH, высокая информационная плотность без визуального шума.
|
|
27
31
|
- Утверждённые референсы: Дизайн-система DeepSeek Harness (`--dsw-alias-*`), чипы в шапке сессии (`dsh-key-rotation`, `dsh-context-lens`), стандарт карточек настроек DSH.
|
|
28
32
|
- Не копировать: Избыточные градиенты, внешние модальные окна, тяжелые тени, кастомные несогласованные шрифты.
|
|
@@ -41,7 +45,7 @@
|
|
|
41
45
|
- Сетка и отступы:
|
|
42
46
|
- Чип: высота 22px, padding: 0 8px, gap: 6px, border-radius: 6px.
|
|
43
47
|
- Панель: padding: 12px 14px, border-radius: 10px, ширина 320px.
|
|
44
|
-
- Карточка настроек: нативный складной контейнер (`.dcm-
|
|
48
|
+
- Карточка настроек: нативный складной контейнер (`.dcm-card`) с шапкой, статусами-бейджами (`dcm-badge-ok`, `dcm-badge-warn`, `dcm-badge-bad`), 3 структурированными секциями (`Основные параметры`, `Каталог OpenRouter`, `Диагностика и статус`), защитой ввода и кнопкой сохранения (`dcm-btn-primary`).
|
|
45
49
|
|
|
46
50
|
## Components & States
|
|
47
51
|
- Чип:
|
|
@@ -82,6 +86,15 @@
|
|
|
82
86
|
- Не допускать утечек локальных путей и инфраструктурных данных в коде или документации.
|
|
83
87
|
|
|
84
88
|
## History & Decisions
|
|
89
|
+
- 2026-09-12 (v0.8.1):
|
|
90
|
+
- Оптимизация производительности расчёта тарифов: замена 1440-минутного цикла на алгоритм O(K) по точкам перехода и мемоизация экстремумов через WeakMap.
|
|
91
|
+
- Серверный кэш разрешения тарифов resolveTariffCache (Map) с автоматической очисткой при обновлении каталога.
|
|
92
|
+
- Поддержка ETag и ответа 304 Not Modified на эндпоинте /dsh-cost-meter/state.
|
|
93
|
+
- Кнопка ручной синхронизации каталога цен в секции OpenRouter с защитой от флуда (cooldown 30 сек).
|
|
94
|
+
- Интеллектуальные подсказки экономии: плашка скорого наступления льготного тарифа (скидка 50%) и отсчёт времени.
|
|
95
|
+
- Поддержка настраиваемого порога бюджета сессии (budgetThreshold) с предупреждающей подсветкой чипа.
|
|
96
|
+
- Кнопка быстрого копирования текстового отчёта о расходах в буфер обмена.
|
|
97
|
+
- Таблица нормализации алиасов вендоров (z-ai -> zai, deepseek-official -> deepseek, gemini -> google).
|
|
85
98
|
- 2026-09-05 (v0.7.9):
|
|
86
99
|
- Hotfix: исправлен ReferenceError (t is not defined) в объекте словаря ru (lib/client.js) (#15).
|
|
87
100
|
- Добавлен автоматический тест на чистое исполнение фабрики client loader (`test/public-route.test.mjs`).
|
package/docs/plans/findings.md
CHANGED
|
@@ -1,22 +1,17 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Findings: Issue #25 (v0.8.1)
|
|
2
2
|
|
|
3
|
-
## 1.
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
2.
|
|
7
|
-
|
|
8
|
-
4. `useOpenRouter` (boolean, default true) -> Missing in UI -> To be added as a checkbox in `CostMeterCard`
|
|
9
|
-
5. `refreshHours` (number, default 24) -> Missing in UI -> To be added as a numeric input in `CostMeterCard`
|
|
10
|
-
6. `modelMap` (dict of string -> string) -> Advanced JSON/YAML route mapping
|
|
11
|
-
7. `prices` (dict of PriceRow) -> Advanced manual pricing rules
|
|
12
|
-
8. `deepseekPeakPrices` (dict of PriceRow) -> Advanced DeepSeek peak overrides
|
|
13
|
-
9. `manualPeakWindowsUtc` (array of string) -> Advanced manual time windows
|
|
14
|
-
10. `manualOffPeakMultiplier` (number) -> Advanced discount multiplier for manual rates
|
|
3
|
+
## 1. Клиентские вычисления расписания
|
|
4
|
+
- В `lib/client.js`: `extremes()` и `minutesUntilChange()` вызывались на каждом тике таймера (15 сек) и перерисовывали 1440-минутный цикл:
|
|
5
|
+
`for (let minute = 0; minute < 1440; minute++)` с поиском в `windows`.
|
|
6
|
+
- В сутках конечное число окон $K$ (обычно 2–4). Смена тарифа может происходить только на границах интервалов: `window.start` и `window.end`.
|
|
7
|
+
- Замена на $O(K)$ даёт мгновенный расчёт без аллокации сотен объектов в секунду при активных сессиях.
|
|
15
8
|
|
|
16
|
-
|
|
9
|
+
## 2. Разрешение тарифов на сервере
|
|
10
|
+
- `resolveTariff(cfg, catalog.index, route)` перебирает регулярные выражения и суффиксы.
|
|
11
|
+
- Кэширование в `Map<string, ResolvedTariff>` с очисткой при обновлении каталога полностью снимает нагрузку на CPU при частом пуллинге `/state` клиентами DSH.
|
|
17
12
|
|
|
18
|
-
##
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
13
|
+
## 3. Поддержка ETag
|
|
14
|
+
- Для `/dsh-cost-meter/state` генерация слабого ETag (`W/"<hash>"`) на основе `updatedAt`, `fetchedAt` и счетчиков токенов позволяет клиентам передавать `If-None-Match` и получать `304 Not Modified`, экономя полосу пропускания и парсинг JSON.
|
|
15
|
+
|
|
16
|
+
## 4. Алиасы вендоров
|
|
17
|
+
- Разные провайдеры в DSH могут передавать вендоров как `z-ai`, `zai`, `google`, `gemini`, `deepseek-ai`, `deepseek`. Единая нормализация исключит ситуации fallback на generic тариф.
|
package/docs/plans/progress.md
CHANGED
|
@@ -1,17 +1,12 @@
|
|
|
1
|
-
# Progress
|
|
1
|
+
# Progress: Issue #25 (v0.8.1)
|
|
2
2
|
|
|
3
|
-
-
|
|
4
|
-
-
|
|
5
|
-
-
|
|
6
|
-
-
|
|
7
|
-
|
|
8
|
-
-
|
|
9
|
-
-
|
|
10
|
-
-
|
|
11
|
-
-
|
|
12
|
-
-
|
|
13
|
-
- [ ] Test package on MiniPC isolated test server (`192.168.1.123:3082`)
|
|
14
|
-
- [ ] Smoke-test package on production candidate (`192.168.1.111:3080`)
|
|
15
|
-
- [ ] Publish v0.7.9 to npm and GitHub Release
|
|
16
|
-
- [ ] Install v0.7.9 from npm on MiniAI and verify live health
|
|
17
|
-
- [ ] Close Gitea Issue #21 and clean up worktree
|
|
3
|
+
- **2026-09-12 19:10**:
|
|
4
|
+
- Создана Gitea Issue #25.
|
|
5
|
+
- Создан worktree `.worktrees/issue-25` от `origin/main` (ветка `feat/issue-25-perf-and-smart-features`).
|
|
6
|
+
- Инициализированы планы в `docs/plans/`.
|
|
7
|
+
|
|
8
|
+
- **2026-09-12 19:16**:
|
|
9
|
+
- Реализованы оптимизации в `lib/index.js` (resolveTariffCache, ETag / 304, POST /refresh, budgetThreshold, VENDOR_ALIASES).
|
|
10
|
+
- Реализованы улучшения в `lib/client.js` (O(K) minutesUntilChange, memoized extremes, кнопка синхронизации с cooldown, порог бюджета, плашка экономии, копирование сводки).
|
|
11
|
+
- Добавлены тесты в `test/v081-perf-smart.test.mjs` (все 20 тестов успешно пройдены).
|
|
12
|
+
- Версия поднята до `0.8.1`.
|
package/docs/plans/task_plan.md
CHANGED
|
@@ -1,32 +1,31 @@
|
|
|
1
|
-
# Task Plan:
|
|
1
|
+
# Task Plan: Issue #25 (v0.8.1) — Оптимизация производительности, ручная синхронизация каталога и подсказки экономии
|
|
2
2
|
|
|
3
|
-
##
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
-
|
|
15
|
-
-
|
|
16
|
-
|
|
17
|
-
-
|
|
3
|
+
## Цели
|
|
4
|
+
1. **Скорость**:
|
|
5
|
+
- Оптимизация алгоритма расчета времени смены тарифа (`minutesUntilChange`) и экстремумов (`extremes`) с $O(1440)$ до $O(K)$ без полного минутного цикла.
|
|
6
|
+
- Серверный кэш `resolveTariffCache` для быстрого разрешения моделей.
|
|
7
|
+
- Поддержка ETag / 304 Not Modified на эндпоинте `/dsh-cost-meter/state`.
|
|
8
|
+
2. **Качество и управление**:
|
|
9
|
+
- Маршрут `POST /dsh-cost-meter/refresh` с rate limit (cooldown 30 сек) и кнопка «Синхронизировать сейчас» в настройках.
|
|
10
|
+
- Таблица нормализации алиасов вендоров (Smart Vendor Aliases).
|
|
11
|
+
- Индикация stale-кэша каталога в UI.
|
|
12
|
+
3. **Экономия**:
|
|
13
|
+
- Подсказка в поповере о приближении льготного тарифа (50% скидка).
|
|
14
|
+
- Конфигурируемый порог сессии `budgetThreshold` с предупреждающей подсветкой чипа.
|
|
15
|
+
- Кнопка «Скопировать сводку» в поповере.
|
|
16
|
+
4. **Стандарты и релиз**:
|
|
17
|
+
- 100% прохождение тестов `npm test`.
|
|
18
|
+
- Проверка размера файлов (< 256 KiB).
|
|
19
|
+
- Тестирование на test server (MiniPC :3082), затем на MiniAI candidate (:3080).
|
|
20
|
+
- Запрос подтверждения пользователя -> публикация v0.8.1 в npm/GitHub -> rollout на прод.
|
|
18
21
|
|
|
19
|
-
##
|
|
20
|
-
- [
|
|
21
|
-
- [
|
|
22
|
-
- [
|
|
23
|
-
- [
|
|
24
|
-
- [
|
|
25
|
-
- [
|
|
26
|
-
- [ ]
|
|
27
|
-
- [ ]
|
|
28
|
-
- [ ]
|
|
29
|
-
- [ ] Test on MiniPC test server (`192.168.1.123`)
|
|
30
|
-
- [ ] Install on production MiniAI (`192.168.1.111`) & verify
|
|
31
|
-
- [ ] Release v0.7.9 on GitHub & npm
|
|
32
|
-
- [ ] Close Issue #21 & cleanup worktree
|
|
22
|
+
## Статус выполнения
|
|
23
|
+
- [x] Issue #25 создана
|
|
24
|
+
- [x] Worktree `.worktrees/issue-25` развёрнут
|
|
25
|
+
- [x] Реализация серверной части (`lib/index.js`)
|
|
26
|
+
- [x] Реализация клиентской части (`lib/client.js`)
|
|
27
|
+
- [x] Добавление unit-тестов в `test/`
|
|
28
|
+
- [x] Обновление документации (`DESIGN.md`, `README.md`, `README.ru.md`)
|
|
29
|
+
- [ ] Тестирование на стендах (:3082, :3080)
|
|
30
|
+
- [ ] Публикация релиза v0.8.1
|
|
31
|
+
- [ ] Закрытие Issue #25 и очистка worktree
|