dsh-cost-meter 1.6.11 → 1.6.12
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 +5 -5
- package/README.md +5 -5
- package/lib/backfill.js +41 -16
- package/lib/index.js +34 -12
- package/package.json +1 -1
package/README.en.md
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
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
|
-
[](https://github.com/Han-1413141/dsh-cost-meter)
|
|
10
10
|
[](https://www.npmjs.com/package/dsh-cost-meter)
|
|
11
11
|
[](LICENSE)
|
|
12
12
|
[](https://github.com/deepseek-ai/deepseek-harness)
|
|
@@ -231,22 +231,22 @@ Real captures from an actual DSH sidebar of the period strip and collapsed verti
|
|
|
231
231
|
dsh plugin --profile web add dsh-cost-meter
|
|
232
232
|
```
|
|
233
233
|
|
|
234
|
-
**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.6.
|
|
234
|
+
**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.6.12`** — review the script before running):
|
|
235
235
|
|
|
236
236
|
```powershell
|
|
237
|
-
irm https://raw.githubusercontent.com/Han-1413141/dsh-cost-meter/v1.6.
|
|
237
|
+
irm https://raw.githubusercontent.com/Han-1413141/dsh-cost-meter/v1.6.12/install.ps1 | iex
|
|
238
238
|
```
|
|
239
239
|
|
|
240
240
|
**Or a plain command line** (the machine must already have pnpm and git; also pinned to the tag):
|
|
241
241
|
|
|
242
242
|
```sh
|
|
243
|
-
dsh plugin --profile web add github:Han-1413141/dsh-cost-meter#v1.6.
|
|
243
|
+
dsh plugin --profile web add github:Han-1413141/dsh-cost-meter#v1.6.12
|
|
244
244
|
```
|
|
245
245
|
|
|
246
246
|
Without git, use the GitHub tag archive:
|
|
247
247
|
|
|
248
248
|
```sh
|
|
249
|
-
dsh plugin --profile web add https://github.com/Han-1413141/dsh-cost-meter/archive/refs/tags/v1.6.
|
|
249
|
+
dsh plugin --profile web add https://github.com/Han-1413141/dsh-cost-meter/archive/refs/tags/v1.6.12.tar.gz
|
|
250
250
|
```
|
|
251
251
|
|
|
252
252
|
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,7 @@
|
|
|
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
|
-
[](https://github.com/Han-1413141/dsh-cost-meter)
|
|
10
10
|
[](https://www.npmjs.com/package/dsh-cost-meter)
|
|
11
11
|
[](LICENSE)
|
|
12
12
|
[](https://github.com/deepseek-ai/deepseek-harness)
|
|
@@ -233,22 +233,22 @@
|
|
|
233
233
|
dsh plugin --profile web add dsh-cost-meter
|
|
234
234
|
```
|
|
235
235
|
|
|
236
|
-
**PowerShell 一键脚本**(复制整行粘贴回车;自动补齐 pnpm、自动探测 git,无需克隆仓库;安装链**固定到发布 tag `v1.6.
|
|
236
|
+
**PowerShell 一键脚本**(复制整行粘贴回车;自动补齐 pnpm、自动探测 git,无需克隆仓库;安装链**固定到发布 tag `v1.6.12`**,建议先下载审阅再运行):
|
|
237
237
|
|
|
238
238
|
```powershell
|
|
239
|
-
irm https://raw.githubusercontent.com/Han-1413141/dsh-cost-meter/v1.6.
|
|
239
|
+
irm https://raw.githubusercontent.com/Han-1413141/dsh-cost-meter/v1.6.12/install.ps1 | iex
|
|
240
240
|
```
|
|
241
241
|
|
|
242
242
|
**或直接命令行**(机器上需已有 pnpm 与 git;同样固定到 tag):
|
|
243
243
|
|
|
244
244
|
```sh
|
|
245
|
-
dsh plugin --profile web add github:Han-1413141/dsh-cost-meter#v1.6.
|
|
245
|
+
dsh plugin --profile web add github:Han-1413141/dsh-cost-meter#v1.6.12
|
|
246
246
|
```
|
|
247
247
|
|
|
248
248
|
没有 git 时可用 GitHub tag 打包直链:
|
|
249
249
|
|
|
250
250
|
```sh
|
|
251
|
-
dsh plugin --profile web add https://github.com/Han-1413141/dsh-cost-meter/archive/refs/tags/v1.6.
|
|
251
|
+
dsh plugin --profile web add https://github.com/Han-1413141/dsh-cost-meter/archive/refs/tags/v1.6.12.tar.gz
|
|
252
252
|
```
|
|
253
253
|
|
|
254
254
|
安装后**重启** `dsh web`(插件行、Typert 清单与客户端 bundle 均在启动时扫描):
|
package/lib/backfill.js
CHANGED
|
@@ -286,6 +286,11 @@ export function replaySessionRecords(records, config, wantDates = null) {
|
|
|
286
286
|
let usage = null
|
|
287
287
|
let turn = 0
|
|
288
288
|
let step = 0
|
|
289
|
+
// compaction/summary(issue #77):压缩摘要调用是真实的一次 provider 计费,
|
|
290
|
+
// 但事件为 log-only、不是循环步——不占 (turn, step),自带路由(provider/
|
|
291
|
+
// model,两代宿主形态 data.message.source.{provider,model} 与
|
|
292
|
+
// data.{provider,model} 都兼容),仅作用于本样本;去重键独立于循环步。
|
|
293
|
+
let isCompaction = false
|
|
289
294
|
// 判空与去重键缺省值与 index.js 投影完全同构(usage null 不入账;turn/step
|
|
290
295
|
// 缺省 0,保证实时投影与回放对同一事件产生同一 (turn,step) 去重键)。
|
|
291
296
|
if (event.type === 'assistant/chunk' && event.data?.chunk?.type === 'usage' && event.data.chunk.usage != null) {
|
|
@@ -296,6 +301,9 @@ export function replaySessionRecords(records, config, wantDates = null) {
|
|
|
296
301
|
usage = event.data.usage
|
|
297
302
|
turn = event.data.turn ?? 0
|
|
298
303
|
step = event.data.step ?? 0
|
|
304
|
+
} else if (event.type === 'compaction/summary' && event.data?.usage != null) {
|
|
305
|
+
usage = event.data.usage
|
|
306
|
+
isCompaction = true
|
|
299
307
|
} else {
|
|
300
308
|
continue
|
|
301
309
|
}
|
|
@@ -310,25 +318,42 @@ export function replaySessionRecords(records, config, wantDates = null) {
|
|
|
310
318
|
cacheWrite: num(usage.cacheWriteTokens),
|
|
311
319
|
reasoning: num(usage.reasoningTokens),
|
|
312
320
|
}
|
|
321
|
+
// 摘要样本的事件自带路由(header 状态不受影响,后续循环步仍按其 header 计费)。
|
|
322
|
+
let sampleProvider = provider
|
|
323
|
+
let sampleModel = model
|
|
324
|
+
if (isCompaction) {
|
|
325
|
+
const source = event.data?.message?.source ?? {}
|
|
326
|
+
if (typeof source.provider === 'string' && source.provider.length > 0) sampleProvider = source.provider
|
|
327
|
+
else if (typeof event.data.provider === 'string' && event.data.provider.length > 0) sampleProvider = event.data.provider
|
|
328
|
+
if (typeof source.model === 'string' && source.model.length > 0) sampleModel = source.model
|
|
329
|
+
else if (typeof event.data.model === 'string' && event.data.model.length > 0) sampleModel = event.data.model
|
|
330
|
+
}
|
|
313
331
|
// modlens 视觉包装层转发对去重(issue #70/#76):包装层样本先改挂上游 id
|
|
314
332
|
// (与账本入账钩子/实时投影同口径),仅当窗口内既无相同 (model, 五桶) 的
|
|
315
333
|
// 非包装样本(预扫描集)、也无本回放已计入的改挂样本时才计入——上游真实流
|
|
316
334
|
// 先到或后到都只计一次。v1.6.10 及之前对包装层一律跳过,整条链路均为包装型
|
|
317
335
|
// id 的转售路由(如 modlens-go-ds4f)因此整单漏计(账本 sessions=0)。
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
336
|
+
// compaction/summary 豁免窗口去重:它是单源事件(摘要结果只写一条日志,
|
|
337
|
+
// 没有包装转发对),与实时投影同口径(既不查窗也不入窗)。
|
|
338
|
+
let effectiveProvider = sampleProvider
|
|
339
|
+
if (isWrapperProviderId(sampleProvider)) {
|
|
340
|
+
effectiveProvider = wrapperUpstreamProvider(sampleProvider) ?? sampleProvider
|
|
341
|
+
if (!isCompaction) {
|
|
342
|
+
const fp = usageFingerprint(sampleModel, buckets)
|
|
343
|
+
remappedAdmitted = remappedAdmitted.filter(entry => atMs - entry.at <= USAGE_DEDUP_WINDOW_MS)
|
|
344
|
+
const plainTimes = plainFingerprints.get(fp)
|
|
345
|
+
const plainHit = plainTimes !== undefined && plainTimes.some(t => Math.abs(atMs - t) <= USAGE_DEDUP_WINDOW_MS)
|
|
346
|
+
if (plainHit || remappedAdmitted.some(entry => entry.fp === fp)) continue
|
|
347
|
+
remappedAdmitted.push({ fp, at: atMs })
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
const key = isCompaction
|
|
351
|
+
? `compaction:${Number.isFinite(Number(event.seq)) && Number(event.seq) >= 0 ? Number(event.seq) : 't' + String(event.time ?? '')}`
|
|
352
|
+
: `${turn}:${step}`
|
|
353
|
+
// 去重与旧版完全一致:单一 (turn,step) 状态机跨种子/own 段连续生效;
|
|
354
|
+
// 摘要键独立,永不与循环步的样本替换相互干扰。
|
|
330
355
|
const prev = last !== null && last.key === key ? last : null
|
|
331
|
-
if (prev !== null && prev.providerKey === `${effectiveProvider}:${
|
|
356
|
+
if (prev !== null && prev.providerKey === `${effectiveProvider}:${sampleModel}`
|
|
332
357
|
&& prev.buckets.input === buckets.input && prev.buckets.output === buckets.output
|
|
333
358
|
&& prev.buckets.cacheRead === buckets.cacheRead && prev.buckets.cacheWrite === buckets.cacheWrite
|
|
334
359
|
&& prev.buckets.reasoning === buckets.reasoning) {
|
|
@@ -336,7 +361,7 @@ export function replaySessionRecords(records, config, wantDates = null) {
|
|
|
336
361
|
}
|
|
337
362
|
// 按事件时刻计费(历史正确):峰谷时代前用 legacyBase,之后按峰谷两档。
|
|
338
363
|
// 计价/归类/归因一律用改挂后的 effectiveProvider(包装层转发对挂语义上游)。
|
|
339
|
-
const resolved = providerPriceEntryFor(effectiveProvider,
|
|
364
|
+
const resolved = providerPriceEntryFor(effectiveProvider, sampleModel, config?.prices, {
|
|
340
365
|
mode: config?.priceMatch === 'exact' ? 'exact' : 'auto',
|
|
341
366
|
overrides: config?.priceOverrides,
|
|
342
367
|
})
|
|
@@ -353,8 +378,8 @@ export function replaySessionRecords(records, config, wantDates = null) {
|
|
|
353
378
|
config?.exchangeRate)
|
|
354
379
|
// Plan/API 双轨分类(issue #64):与 store.account() 同一分类器,回放条目
|
|
355
380
|
// 的 apiCost 只含真金白银部分(plan 类金额仅记等值);传 prices 供路由判定。
|
|
356
|
-
const apiCost = billingClassOf(effectiveProvider,
|
|
357
|
-
const providerKey = `${effectiveProvider}:${
|
|
381
|
+
const apiCost = billingClassOf(effectiveProvider, sampleModel, config?.planBilling, enabledPlanSetOf(config), config?.prices) === 'api' ? cost : 0
|
|
382
|
+
const providerKey = `${effectiveProvider}:${sampleModel}`
|
|
358
383
|
// 聚合目标按事件分段路由;被替换的旧样本从它当时所在的段扣回(与旧版
|
|
359
384
|
// 单流先减后加的净效果一致,仅种子段的量落到 seedDays 而非 days)。
|
|
360
385
|
if (prev !== null) shift(prev, -1, prev.seed ? seedDays : days)
|
package/lib/index.js
CHANGED
|
@@ -346,7 +346,9 @@ function makeCostUsageProjection(ledger) {
|
|
|
346
346
|
// v5→v6(issue #61):seedLength/seedDeducted 延迟扣除,修复“种子段含父会话自己的 end-seed”
|
|
347
347
|
// 导致的首个边界过小、中间种子漏扣的问题;取种子段内最大 end-seed,延迟至首个 own 事件再整段扣回。
|
|
348
348
|
// v6→v7(issue #63):seedLength 仅显式取值,普通会话的 length 不再误作种子边界,避免非 fork 会话代币漏计。
|
|
349
|
-
|
|
349
|
+
// v7→v8(issue #77):折叠计入 compaction/summary(压缩摘要调用,此前漏计);
|
|
350
|
+
// 升版本触发宿主对旧 checkpoint 全量重放,历史摘要调用量随之补齐。
|
|
351
|
+
stateVersion: 8,
|
|
350
352
|
init: () => ({ provider: 'deepseek', model: 'default', totals: zeroBuckets(), byModel: {}, byProviderModel: {}, last: null, createdAt: 0, seedEndSeq: -1, shadow: emptyShadow(), seedLength: -1, seedDeducted: false, recent: [] }),
|
|
351
353
|
apply(state, event) {
|
|
352
354
|
// 兼容旧 checkpoint 的缺字段(版本升级前持久化的 v5 状态):缺省回落。
|
|
@@ -439,6 +441,14 @@ function makeCostUsageProjection(ledger) {
|
|
|
439
441
|
let usage = null
|
|
440
442
|
let turn = 0
|
|
441
443
|
let step = 0
|
|
444
|
+
// compaction/summary(issue #77):压缩摘要调用是真实的一次 provider 计费
|
|
445
|
+
// (走 ctx.llm.stream,实时账本钩子本就覆盖),但事件为 log-only、不是循环步
|
|
446
|
+
// ——不占 (turn, step),自带路由(provider/model,两代宿主形态:
|
|
447
|
+
// data.message.source.{provider,model} 与 data.{provider,model} 都兼容)。
|
|
448
|
+
// 折叠按事件自带路由归因,缺省回落 header 状态;去重键独立于循环步。
|
|
449
|
+
let eventProvider = null
|
|
450
|
+
let eventModel = null
|
|
451
|
+
let keyOverride = null
|
|
442
452
|
// 判空用 != null:usage === null 时 !== undefined 会放行,随后读
|
|
443
453
|
// usage.inputTokens 直接抛 TypeError 打断投影;billing-stream 侧同处
|
|
444
454
|
// 还会让 null 覆盖先前捕获的有效 usage 快照导致整次调用漏计。
|
|
@@ -450,6 +460,15 @@ function makeCostUsageProjection(ledger) {
|
|
|
450
460
|
usage = event.data.usage
|
|
451
461
|
turn = event.data.turn ?? 0
|
|
452
462
|
step = event.data.step ?? 0
|
|
463
|
+
} else if (event.type === 'compaction/summary' && event.data?.usage != null) {
|
|
464
|
+
usage = event.data.usage
|
|
465
|
+
const source = event.data.message?.source ?? {}
|
|
466
|
+
eventProvider = typeof source.provider === 'string' && source.provider.length > 0 ? source.provider
|
|
467
|
+
: (typeof event.data.provider === 'string' && event.data.provider.length > 0 ? event.data.provider : null)
|
|
468
|
+
eventModel = typeof source.model === 'string' && source.model.length > 0 ? source.model
|
|
469
|
+
: (typeof event.data.model === 'string' && event.data.model.length > 0 ? event.data.model : null)
|
|
470
|
+
const seqNum = Number(event.seq)
|
|
471
|
+
keyOverride = `compaction:${Number.isFinite(seqNum) && seqNum >= 0 ? seqNum : 't' + String(event.time ?? '')}`
|
|
453
472
|
} else {
|
|
454
473
|
return state
|
|
455
474
|
}
|
|
@@ -460,9 +479,10 @@ function makeCostUsageProjection(ledger) {
|
|
|
460
479
|
// (issue #76)。v1.6.11 起与账本入账钩子同语义:包装层样本先改挂上游 id,
|
|
461
480
|
// 再按 (model, 五桶指纹) 10s 窗与已计入样本互斥——上游真实流先到或后到
|
|
462
481
|
// 都只计一次;包装层单链照常计入,不再整单漏计。
|
|
463
|
-
const rawProvider = typeof state.provider === 'string' ? state.provider : ''
|
|
482
|
+
const rawProvider = typeof (eventProvider ?? state.provider) === 'string' ? (eventProvider ?? state.provider) : ''
|
|
464
483
|
const wrapped = isWrapperProviderId(rawProvider)
|
|
465
484
|
const effectiveProvider = wrapped ? (wrapperUpstreamProvider(rawProvider) ?? rawProvider) : rawProvider
|
|
485
|
+
const model = typeof eventModel === 'string' && eventModel.length > 0 ? eventModel : state.model
|
|
466
486
|
const buckets = {
|
|
467
487
|
input: usage.inputTokens ?? 0,
|
|
468
488
|
output: usage.outputTokens ?? 0,
|
|
@@ -470,9 +490,9 @@ function makeCostUsageProjection(ledger) {
|
|
|
470
490
|
cacheWrite: usage.cacheWriteTokens ?? 0,
|
|
471
491
|
reasoning: usage.reasoningTokens ?? 0,
|
|
472
492
|
}
|
|
473
|
-
const key = `${turn}:${step}`
|
|
493
|
+
const key = keyOverride ?? `${turn}:${step}`
|
|
474
494
|
const prev = state.last !== null && state.last.key === key ? state.last : null
|
|
475
|
-
if (prev !== null && prev.provider === effectiveProvider && prev.model ===
|
|
495
|
+
if (prev !== null && prev.provider === effectiveProvider && prev.model === model
|
|
476
496
|
&& prev.buckets.input === buckets.input && prev.buckets.output === buckets.output
|
|
477
497
|
&& prev.buckets.cacheRead === buckets.cacheRead && prev.buckets.cacheWrite === buckets.cacheWrite
|
|
478
498
|
&& prev.buckets.reasoning === buckets.reasoning) {
|
|
@@ -482,18 +502,20 @@ function makeCostUsageProjection(ledger) {
|
|
|
482
502
|
const atMs = Number.isFinite(Number(event.time)) && Number(event.time) > 0 ? Number(event.time) : Date.now()
|
|
483
503
|
// 指纹窗口去重(与 lib/usage-dedup.js 同语义的序列化形态):先按窗口清扫
|
|
484
504
|
// 滚动列表,重复转发跳过(清扫结果仍落回 state,保持窗口推进)。有界:
|
|
485
|
-
// 超过 24 条先截断再判定,checkpoint 体积恒定。
|
|
486
|
-
|
|
505
|
+
// 超过 24 条先截断再判定,checkpoint 体积恒定。compaction/summary 不参与:
|
|
506
|
+
// 它是单源事件(摘要结果只写一条日志,没有包装转发对),豁免既消除与
|
|
507
|
+
// 邻近循环步同指纹的极小误杀面,也避免它影响其它样本的窗口判定。
|
|
508
|
+
const fp = usageFingerprint(model, buckets)
|
|
487
509
|
let recent = (Array.isArray(state.recent) ? state.recent : [])
|
|
488
510
|
.filter(entry => entry !== null && typeof entry === 'object' && atMs - entry.at <= USAGE_DEDUP_WINDOW_MS)
|
|
489
511
|
if (recent.length > 24) recent = recent.slice(-24)
|
|
490
512
|
const hitPlain = recent.some(entry => entry.w !== 1 && entry.fp === fp)
|
|
491
513
|
const hitRemapped = recent.some(entry => entry.w === 1 && entry.fp === fp)
|
|
492
|
-
if (wrapped ? (hitPlain || hitRemapped) : hitRemapped) {
|
|
514
|
+
if (keyOverride === null && (wrapped ? (hitPlain || hitRemapped) : hitRemapped)) {
|
|
493
515
|
return { ...state, recent }
|
|
494
516
|
}
|
|
495
|
-
recent.push({ fp, at: atMs, ...(wrapped ? { w: 1 } : {}) })
|
|
496
|
-
const resolved = providerPriceEntryFor(effectiveProvider,
|
|
517
|
+
if (keyOverride === null) recent.push({ fp, at: atMs, ...(wrapped ? { w: 1 } : {}) })
|
|
518
|
+
const resolved = providerPriceEntryFor(effectiveProvider, model, ledger.config?.prices, {
|
|
497
519
|
mode: ledger.config?.priceMatch === 'exact' ? 'exact' : 'auto',
|
|
498
520
|
overrides: ledger.config?.priceOverrides,
|
|
499
521
|
})
|
|
@@ -545,14 +567,14 @@ function makeCostUsageProjection(ledger) {
|
|
|
545
567
|
}
|
|
546
568
|
}
|
|
547
569
|
if (prev !== null) shiftInto(mainAgg, prev.provider, prev.model, prev.buckets, prev.cost, -1)
|
|
548
|
-
shiftInto(mainAgg, effectiveProvider,
|
|
570
|
+
shiftInto(mainAgg, effectiveProvider, model, buckets, billed, 1)
|
|
549
571
|
if (mirrorSeed) {
|
|
550
572
|
if (prev !== null) shiftInto(shadowAgg, prev.provider, prev.model, prev.buckets, prev.cost, -1)
|
|
551
|
-
shiftInto(shadowAgg, effectiveProvider,
|
|
573
|
+
shiftInto(shadowAgg, effectiveProvider, model, buckets, billed, 1)
|
|
552
574
|
}
|
|
553
575
|
// createdAt/seedLength/seedDeducted 必须随状态携带:usage 样本更新不能丢掉 fork 过滤基准。
|
|
554
576
|
// recent 随行:包装层转发对去重的滚动窗口状态(有界 ≤25 条)。
|
|
555
|
-
return { provider: state.provider, model: state.model, totals, byModel, byProviderModel, createdAt: state.createdAt, seedEndSeq: state.seedEndSeq, seedLength: state.seedLength, seedDeducted: state.seedDeducted, shadow: shadowAgg, recent, last: { key, provider: effectiveProvider, model
|
|
577
|
+
return { provider: state.provider, model: state.model, totals, byModel, byProviderModel, createdAt: state.createdAt, seedEndSeq: state.seedEndSeq, seedLength: state.seedLength, seedDeducted: state.seedDeducted, shadow: shadowAgg, recent, last: { key, provider: effectiveProvider, model, buckets, cost: billed } }
|
|
556
578
|
},
|
|
557
579
|
view: projectionView,
|
|
558
580
|
// DSH 0.1.1-rc.1 起会话投影需声明 wire 才会向客户端推送(PR #39 by
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-cost-meter",
|
|
3
|
-
"version": "1.6.
|
|
3
|
+
"version": "1.6.12",
|
|
4
4
|
"description": "DeepSeek Harness 会话费用统计插件:本会话成本、当日费用、历史记录与官方价格同步,支持多厂商多模型价格计费(内置 90+ 模型价格目录与自动匹配)、主流 Coding Plan 订阅额度查询与显示(9 家,含 SCNet Token Plan 本地 Credits 计量与火山方舟 Volcano Ark Coding Plan AK/SK 签名查询)、自定义 Provider 余额查询(可配任意 HTTP 端点)与余额进度条、峰谷计价时段显示与切换前弹窗/系统通知提醒(位置/提前量/类型可配),界面中英双语。Session cost tracking plugin for DeepSeek Harness: per-conversation cost, daily totals, history and official price sync, with multi-vendor model pricing (built-in 90+ model catalog with auto-matching), Coding Plan quota queries & display for 9 vendors (incl. local credits metering for the SCNet Token Plan and Volcano Ark Coding Plan via AK/SK signature), plan/API dual-track billing with per-1% & full-window Token Plan usage estimates, custom provider balance lookup (configurable HTTP endpoint) and balance progress bar, plus peak/off-peak pricing display with pre-switch popup & system-notification alerts (position / lead time / type configurable), in a bilingual (Chinese/English) UI.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "lib/index.js",
|