dsh-cost-meter 1.7.19 → 1.7.21

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.en.md CHANGED
@@ -6,7 +6,10 @@
6
6
 
7
7
  Per-conversation cost · daily totals · OpenCode Go subscription quota display · budget with usage percentage · official account balance · custom provider balance · balance progress bar · history · peak/off-peak pricing hours display (peak hours UTC 01:00–04:00, 06:00–10:00; from Aug 23, 2026 weekends are billed at off-peak prices all day, shown as “Weekend — all off-peak”) · pre-switch popup & system-notification alerts for peak/off-peak changes (position / lead time / alert type configurable) · one-click price sync from the official docs · Codex-style token usage heat grid · multi-vendor model pricing (built-in 90+ model price catalog with auto-matching) · mainstream Coding Plan quota queries & display (Anthropic / Z.ai / MiniMax / Kimi / OpenRouter / SiliconFlow / CommandCode / SCNet) plan/API dual-track billing (subscription quota vs pay-as-you-go money separated, per-1% & full-window token/equivalent-cost estimates with daily/weekly/monthly curves) · · quota strip above the input box (budget / Go / coding-plan usage in one row, toggleable)
8
8
 
9
- [![version](https://img.shields.io/badge/version-1.7.19-4176E6)](https://github.com/Han-1413141/dsh-cost-meter)
9
+ [![version](https://img.shields.io/badge/version-1.7.21-4176E6)](https://github.com/Han-1413141/dsh-cost-meter)
10
+
11
+ **v1.7.21** fixes session costs lost after restart. Settings → Cost → Display adds optional subagent cost aggregation and Codex quota display (both off by default). Gateway cards support account switching. See [native DeepSeek search accounting](docs/native-search-billing.md) and [GPT-6 Astra pricing](docs/gpt-astra-pricing.md).
12
+
10
13
  [![npm](https://img.shields.io/npm/v/dsh-cost-meter?label=npm)](https://www.npmjs.com/package/dsh-cost-meter)
11
14
  [![license](https://img.shields.io/badge/license-MIT-green)](LICENSE)
12
15
  [![dsh](https://img.shields.io/badge/DeepSeek%20Harness-dsh--plugin-4176E6)](https://github.com/deepseek-ai/deepseek-harness)
@@ -258,22 +261,22 @@ Real captures from an actual DSH sidebar of the period strip and collapsed verti
258
261
  dsh plugin --profile web add dsh-cost-meter
259
262
  ```
260
263
 
261
- **PowerShell one-click script** (copy the whole line, paste, press Enter; pnpm is provisioned automatically, git is auto-detected — no clone needed; the install chain is **pinned to the release tag `v1.7.19`** — review the script before running):
264
+ **PowerShell one-click script** (copy the whole line, paste, press Enter; pnpm is provisioned automatically, git is auto-detected — no clone needed; the install chain is **pinned to the release tag `v1.7.21`** — review the script before running):
262
265
 
263
266
  ```powershell
264
- irm https://raw.githubusercontent.com/Han-1413141/dsh-cost-meter/v1.7.19/install.ps1 | iex
267
+ irm https://raw.githubusercontent.com/Han-1413141/dsh-cost-meter/v1.7.21/install.ps1 | iex
265
268
  ```
266
269
 
267
270
  **Or a plain command line** (the machine must already have pnpm and git; also pinned to the tag):
268
271
 
269
272
  ```sh
270
- dsh plugin --profile web add github:Han-1413141/dsh-cost-meter#v1.7.19
273
+ dsh plugin --profile web add github:Han-1413141/dsh-cost-meter#v1.7.21
271
274
  ```
272
275
 
273
276
  Without git, use the GitHub tag archive:
274
277
 
275
278
  ```sh
276
- dsh plugin --profile web add https://github.com/Han-1413141/dsh-cost-meter/archive/refs/tags/v1.7.19.tar.gz
279
+ dsh plugin --profile web add https://github.com/Han-1413141/dsh-cost-meter/archive/refs/tags/v1.7.21.tar.gz
277
280
  ```
278
281
 
279
282
  After installing, **restart** `dsh web` (plugin rows, the Typert manifest and the client bundle are all scanned at startup):
package/README.md CHANGED
@@ -6,7 +6,10 @@
6
6
 
7
7
  本会话费用 · 当日费用 · OpenCode Go 订阅额度显示 · 预算与已用百分比 · 官方账户余额 · 自定义 Provider 余额查询(可配任意 HTTP 端点) · 余额三段进度条 · 历史记录 · 峰谷计价时段显示(UTC 01:00–04:00、06:00–10:00 为峰时段;2026-08-23 起周末全天按谷价,显示「周末时段——全谷价」) · 峰/谷切换前弹窗与系统通知提醒(位置/提前量/提醒类型可配) · 官方价格一键同步 · 类 Codex Token 用量热图 · 多厂商多模型价格计费(内置 90+ 模型价格目录与自动匹配) · 主流 Coding Plan 额度查询与显示(Anthropic / Z.ai / MiniMax / Kimi / OpenRouter / SiliconFlow / CommandCode / SCNet / 火山方舟 九家,含 Volcano Ark AK/SK 签名) · Plan/API 双轨计费(订阅额度与按量金额分离统计,每 1% 额度与满窗的 token/等值金额估算及日/周/月曲线) · 输入框上方额度横条(预算/Go/Coding Plan 用量一条横排显示,可开关)
8
8
 
9
- [![version](https://img.shields.io/badge/version-1.7.19-4176E6)](https://github.com/Han-1413141/dsh-cost-meter)
9
+ [![version](https://img.shields.io/badge/version-1.7.21-4176E6)](https://github.com/Han-1413141/dsh-cost-meter)
10
+
11
+ **v1.7.21**:修复重启后会话费用少算;「设置 → 费用 → 显示」可开启子代理费用合并及 Codex 额度(均默认关闭)。网关额度支持多账号切换。新增 [DeepSeek 原生搜索计量](docs/native-search-billing.md) 与 [GPT-6 Astra 完整计价](docs/gpt-astra-pricing.md)。
12
+
10
13
  [![npm](https://img.shields.io/npm/v/dsh-cost-meter?label=npm)](https://www.npmjs.com/package/dsh-cost-meter)
11
14
  [![license](https://img.shields.io/badge/license-MIT-green)](LICENSE)
12
15
  [![dsh](https://img.shields.io/badge/DeepSeek%20Harness-dsh--plugin-4176E6)](https://github.com/deepseek-ai/deepseek-harness)
@@ -260,22 +263,22 @@
260
263
  dsh plugin --profile web add dsh-cost-meter
261
264
  ```
262
265
 
263
- **PowerShell 一键脚本**(复制整行粘贴回车;自动补齐 pnpm、自动探测 git,无需克隆仓库;安装链**固定到发布 tag `v1.7.19`**,建议先下载审阅再运行):
266
+ **PowerShell 一键脚本**(复制整行粘贴回车;自动补齐 pnpm、自动探测 git,无需克隆仓库;安装链**固定到发布 tag `v1.7.21`**,建议先下载审阅再运行):
264
267
 
265
268
  ```powershell
266
- irm https://raw.githubusercontent.com/Han-1413141/dsh-cost-meter/v1.7.19/install.ps1 | iex
269
+ irm https://raw.githubusercontent.com/Han-1413141/dsh-cost-meter/v1.7.21/install.ps1 | iex
267
270
  ```
268
271
 
269
272
  **或直接命令行**(机器上需已有 pnpm 与 git;同样固定到 tag):
270
273
 
271
274
  ```sh
272
- dsh plugin --profile web add github:Han-1413141/dsh-cost-meter#v1.7.19
275
+ dsh plugin --profile web add github:Han-1413141/dsh-cost-meter#v1.7.21
273
276
  ```
274
277
 
275
278
  没有 git 时可用 GitHub tag 打包直链:
276
279
 
277
280
  ```sh
278
- dsh plugin --profile web add https://github.com/Han-1413141/dsh-cost-meter/archive/refs/tags/v1.7.19.tar.gz
281
+ dsh plugin --profile web add https://github.com/Han-1413141/dsh-cost-meter/archive/refs/tags/v1.7.21.tar.gz
279
282
  ```
280
283
 
281
284
  安装后**重启** `dsh web`(插件行、Typert 清单与客户端 bundle 均在启动时扫描):
@@ -1,9 +1,26 @@
1
1
  {
2
- "generatedAt": "2026-09-01",
2
+ "generatedAt": "2026-09-11",
3
3
  "note": "Auto-generated from lib/pricing.js DEFAULT_PROVIDER_PRICE_TABLE. USD per 1M tokens; unpriced entries have no verified official price.",
4
4
  "providers": {
5
5
  "openai": {
6
6
  "models": {
7
+ "gpt-6-astra": {
8
+ "input": 10,
9
+ "cachedInput": 1,
10
+ "cacheWrite": 12.5,
11
+ "output": 50,
12
+ "longContext": {
13
+ "aboveInputTokens": 272000,
14
+ "cacheMiss": 20,
15
+ "cacheHit": 2,
16
+ "cacheWrite": 25,
17
+ "output": 75
18
+ },
19
+ "billingMode": "flat",
20
+ "sourceUrl": "https://developers.openai.com/api/docs/models/gpt-6-astra",
21
+ "checkedAt": "2026-09-11",
22
+ "notes": "标准 API 价,OpenCode Zen 同价;完整输入(含缓存读写)超过 272K 时整次请求按长上下文档计费;不含 Batch/Flex/Fast 服务档折扣或倍率"
23
+ },
7
24
  "gpt-5.6-sol": {
8
25
  "input": 2,
9
26
  "cachedInput": 0.2,
package/lib/backfill.js CHANGED
@@ -18,6 +18,7 @@ import { costOf, providerPriceEntryFor, usdFromCost, isWrapperProviderId, wrappe
18
18
  import { localDayKey, zeroDay, splitLedgerApiCost } from './store.js'
19
19
  import { billingClassOf, enabledPlanSetOf } from './plan-billing.js'
20
20
  import { USAGE_DEDUP_WINDOW_MS, usageFingerprint } from './usage-dedup.js'
21
+ import { isNativeSearchUsageEvent } from './native-search-billing.js'
21
22
 
22
23
  const ZSTD_MAGIC = 4247762216
23
24
  /** 打包行(文本/推理/工具调用增量游程)不含 header 与 usage,回放时跳过。 */
@@ -371,6 +372,7 @@ export function replaySessionRecords(records, config, wantDates = null) {
371
372
  }
372
373
  // 本回放已计入的改挂样本(fp + 时刻):包装层重复分发(窗口内同指纹两次)只计一次。
373
374
  let remappedAdmitted = []
375
+ const nativeSearchIds = new Set()
374
376
  for (const event of records) {
375
377
  if (event === null || typeof event !== 'object') continue
376
378
  if (event.type === 'session' && typeof event.id === 'string') {
@@ -407,6 +409,7 @@ export function replaySessionRecords(records, config, wantDates = null) {
407
409
  // model,两代宿主形态 data.message.source.{provider,model} 与
408
410
  // data.{provider,model} 都兼容),仅作用于本样本;去重键独立于循环步。
409
411
  let isCompaction = false
412
+ const isNativeSearch = isNativeSearchUsageEvent(event)
410
413
  // 判空与去重键缺省值与 index.js 投影完全同构(usage null 不入账;turn/step
411
414
  // 缺省 0,保证实时投影与回放对同一事件产生同一 (turn,step) 去重键)。
412
415
  if (event.type === 'assistant/chunk' && event.data?.chunk?.type === 'usage' && event.data.chunk.usage != null) {
@@ -417,13 +420,17 @@ export function replaySessionRecords(records, config, wantDates = null) {
417
420
  usage = event.data.usage
418
421
  turn = event.data.turn ?? 0
419
422
  step = event.data.step ?? 0
423
+ } else if (isNativeSearch && event.data?.usage != null && typeof event.data.requestId === 'string') {
424
+ if (nativeSearchIds.has(event.data.requestId)) continue
425
+ nativeSearchIds.add(event.data.requestId)
426
+ usage = event.data.usage
420
427
  } else if (event.type === 'compaction/summary' && event.data?.usage != null) {
421
428
  usage = event.data.usage
422
429
  isCompaction = true
423
430
  } else {
424
431
  continue
425
432
  }
426
- const atMs = eventMs
433
+ const atMs = isNativeSearch ? Number(event.data.startedAtMs) : eventMs
427
434
  if (!Number.isFinite(atMs) || atMs <= 0) continue
428
435
  const date = localDayKey(atMs)
429
436
  if (wantDates !== null && !wantDates.has(date)) continue
@@ -437,7 +444,7 @@ export function replaySessionRecords(records, config, wantDates = null) {
437
444
  // 摘要样本的事件自带路由(header 状态不受影响,后续循环步仍按其 header 计费)。
438
445
  let sampleProvider = provider
439
446
  let sampleModel = model
440
- if (isCompaction) {
447
+ if (isCompaction || isNativeSearch) {
441
448
  const source = event.data?.message?.source ?? {}
442
449
  if (typeof source.provider === 'string' && source.provider.length > 0) sampleProvider = source.provider
443
450
  else if (typeof event.data.provider === 'string' && event.data.provider.length > 0) sampleProvider = event.data.provider
@@ -454,7 +461,7 @@ export function replaySessionRecords(records, config, wantDates = null) {
454
461
  let effectiveProvider = sampleProvider
455
462
  if (isWrapperProviderId(sampleProvider)) {
456
463
  effectiveProvider = wrapperUpstreamProvider(sampleProvider) ?? sampleProvider
457
- if (!isCompaction) {
464
+ if (!isCompaction && !isNativeSearch) {
458
465
  const fp = usageFingerprint(sampleModel, buckets)
459
466
  remappedAdmitted = remappedAdmitted.filter(entry => atMs - entry.at <= USAGE_DEDUP_WINDOW_MS)
460
467
  const plainTimes = plainFingerprints.get(fp)
@@ -463,7 +470,7 @@ export function replaySessionRecords(records, config, wantDates = null) {
463
470
  remappedAdmitted.push({ fp, at: atMs })
464
471
  }
465
472
  }
466
- const key = isCompaction
473
+ const key = isNativeSearch ? `search:${event.data.requestId}` : isCompaction
467
474
  ? `compaction:${Number.isFinite(Number(event.seq)) && Number(event.seq) >= 0 ? Number(event.seq) : 't' + String(event.time ?? '')}`
468
475
  : `${turn}:${step}`
469
476
  // 去重与旧版完全一致:单一 (turn,step) 状态机跨种子/own 段连续生效;
@@ -501,7 +508,7 @@ export function replaySessionRecords(records, config, wantDates = null) {
501
508
  if (prev !== null) shift(prev, -1, prev.seed ? seedDays : days)
502
509
  const sample = { key, date, providerKey, buckets, cost, apiCost, seed: isSeed }
503
510
  shift(sample, 1, isSeed ? seedDays : days)
504
- last = sample
511
+ if (!isNativeSearch) last = sample
505
512
  }
506
513
  return { sessionId, title, createdAt, days, seedDays }
507
514
  }