dsh-tokenlens 1.6.0 → 1.6.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/CHANGELOG.md +22 -2
- package/README.md +1 -1
- package/client.js +31 -8
- package/index.js +6 -2
- package/lib/design-plan-cost.mjs +67 -18
- package/lib/design-plan-ledger.mjs +28 -6
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -4,15 +4,35 @@
|
|
|
4
4
|
|
|
5
5
|
**版本记录约定**:同一发布日只保留一个章节,标题取当日**最后一个**已发布版本号;当日多次发布的改动合并到该章节,并在标题下注明当日实际发布过的版本号(npm 上仍可安装这些独立版本)。若当日已有发布,后续小改动不再单独增加版本号,而是并入下一篇日志。这样日志按天规整、不出现同日多个小版本。
|
|
6
6
|
|
|
7
|
+
## 1.6.4 — 2026-11-04
|
|
8
|
+
|
|
9
|
+
(当日已发布版本:v1.6.2 / v1.6.4。v1.6.1 的混合模型修复未单独发版,已并入本节)
|
|
10
|
+
|
|
11
|
+
- **fix(open-design): 「本期 Design Plan 累计」改为只统计 Design Plan 额度消耗,排除钱包余额付费**——钱包扣费不消耗 credits(只扣 `balanceUsd`),所以改由**服务端 credits 反推**金额:`usedCredits ÷ creditsPerUsd ÷ 倍率`。实测 150,005 credits ÷ 10,000 ÷ 0.5 = **$30.00**,与「周额度 $30 × 已用比例」交叉验证一致($30 × 100% = $30.00)。此前按本机 Token × 单价计价,会把钱包付费的调用也算进去,导致两个口径混淆
|
|
12
|
+
- feat(open-design): 新增 `localPricedUsd`(含钱包付费的本机估算)单独保留;当它高于 Design Plan 金额时,弹窗追加「另有 $X 由账户余额支付,未计入」,两个口径都清楚可查
|
|
13
|
+
- **fix(ui): 图表模式日期标签对不齐柱子**——原来把第一个标签钉在左边缘、最后一个钉在右边缘,而柱子是等分 flex 单元格居中的:只有 3 天数据时第一个标签在 0% 而柱子中心在 16.7%,标签整体漂移。改为每个标签居中于**自己那根柱子**的正下方(`(i+0.5)/n`),并放开 x 轴 `overflow` 让边缘标签不被裁掉
|
|
14
|
+
- 测试:332 → 335(Design Plan 金额来自 credits 且低于含钱包的本机估算、无倍率时回退到 credits 面值、3 根柱时标签中心为 16.7%/50%/83.3% 且不贴边)
|
|
15
|
+
|
|
16
|
+
## 1.6.2 — 2026-11-04
|
|
17
|
+
|
|
18
|
+
(当日已发布版本:v1.6.2。v1.6.1 的混合模型修复未单独发版,已并入本节)
|
|
19
|
+
|
|
20
|
+
- **fix(open-design): 混合模型按 credits 加权取额度,不再取最高倍率**——原实现取「用过的最高倍率」当口径,实测 0.5× 与 4× 各占一半 credits 时会把月额度报成 $15(正确应为 **$67.50**),严重低估。现改为按实际消耗加权的调和平均:`m_eff = Σcredits / Σ(credits/m)`,`月额度 = $60 / m_eff`。90% credits 走 0.5× 时是 **$97.89**,99% 时 **$117.92**,偶尔用一次 4× 模型不再摧毁额度
|
|
21
|
+
- fix(open-design): 单一模型时加权公式**精确退化**为官方表格值(0.5×→$120、1×→$60、2×→$30、4×→$15),纯模型场景不受影响
|
|
22
|
+
- fix(open-design): 无消费权重(仅知道模型列表)时回退到最高倍率,即保守口径(承诺最少剩余额度)
|
|
23
|
+
- **fix(open-design): 未收录价格的模型不再静默少算金额**——`unpricedModels` 此前算出来却没有用上,含未知模型时金额会**偏低却不提示**。现在置 `partial: true`,弹窗显示「含未收录价格的模型,金额为下限」,绝不把下限当完整值
|
|
24
|
+
- 测试:328 → 332(切换模型时金额与额度反向变化、未收录模型使金额成为下限、加权混合三种比例、单一模型退化、无权重回退最高倍率)
|
|
25
|
+
- 备注:`600,000 credits/月` 是插件由「7 天窗口上限 × 4」推算的值(官方定价表月/周 = $120/$30 = 4),**不是服务端字段**;服务端只返回 5 小时 50,000 与 7 天 150,000 两个窗口
|
|
26
|
+
|
|
7
27
|
## 1.6.0 — 2026-11-03
|
|
8
28
|
|
|
9
29
|
- **feat(open-design): 「本期 Design Plan 累计」改按官方定价表的模型单价计算**——原来是 `usedCredits ÷ creditsPerUsd`,这个算法隐含「按 1× 倍率消耗」的假设,而官方倍率表跨度 0.25×–4×:对 DeepSeek V4.1 Flash(0.5×)会**少算一半**,对 GPT-6 Luna(4×)会**多算 4 倍**。现在按每个模型的实际 Token × 官方单价(输入/输出/缓存读分别计价)累加,结果可直接与定价表比对
|
|
10
30
|
- **feat(open-design): 给出与倍率匹配的月额度**——定价表里 $120 是**列表价**口径且按倍率消耗:只用 0.5× 模型(DeepSeek V4.1 Flash)可动用**完整 $120**,1× 用 $60,2× 用 $30,4× 用 $15。弹窗改为显示「**已用 / 月额度 + 百分比**」(如 `$27.31 / $120.00 22.8%`),并注明「按 0.5× 倍率模型计价」
|
|
11
|
-
- feat(open-design):
|
|
31
|
+
- feat(open-design): 混合模型取额度口径(v1.6.2 修正为按 credits 加权,不再是最高倍率)
|
|
12
32
|
- feat(wire): `designPlan` 新增 `monthlyCapUsd` / `capPercent` / `multiplier` / `creditsUsd`;`estimatedUsd` 语义改为「官方单价口径的消费额」,旧算法结果保留在 `creditsUsd` 便于对照
|
|
13
33
|
- feat(stats): `models[].last30Days` 增加 `input` / `output` / `cacheRead` / `cacheWrite` 拆分,供按单价计价使用(此前只有 total)
|
|
14
34
|
- fix(open-design): 单价表按官方文档转录 13 个 Design Plan 模型;`hunyuan-h4-preview` / `glm-5.3-flash-x` 不在公开价目接口里,价格缺失时按「未定价」处理并如实上报,绝不臆造
|
|
15
|
-
- 测试:318 → 328(倍率阶梯 0.5×→$120 / 1×→$60 / 2×→$30 / 4×→$15
|
|
35
|
+
- 测试:318 → 328(倍率阶梯 0.5×→$120 / 1×→$60 / 2×→$30 / 4×→$15、未知模型不臆造倍率与额度、按 token 种类计价、**用控制台真实账单核对:$0.0048 列表价 × 0.5 = $0.0024 实扣**、未定价模型上报)
|
|
16
36
|
|
|
17
37
|
## 1.5.3 — 2026-11-03
|
|
18
38
|
|
package/README.md
CHANGED
|
@@ -440,7 +440,7 @@ Host 半注册 `tokenlens_usage`,参数 `action`(默认 `snapshot`)与可
|
|
|
440
440
|
|
|
441
441
|
## 验证
|
|
442
442
|
|
|
443
|
-
- `node --test`:**
|
|
443
|
+
- `node --test`:**332 个自动化用例**,覆盖 Host 数据层、供应商适配器、统计折叠、各 harness 读取、Design Plan 周期账本与官方单价计价、窗口锚点切片、工作区自动识别、插件集成与浏览器端渲染 / 交互。
|
|
444
444
|
- 在真实环境中验证过 **5 个 harness** 的数据源;本机统计与独立的 SQLite 查询、独立的日志解析逐项对账(差额为 0),跨 harness 合并与供应商映射算术自洽。
|
|
445
445
|
- 供应商接口按各官方文档与参考客户端行为验证;未配置凭据时 chip 静默隐藏,接口异常时按可重试错误降级。
|
|
446
446
|
|
package/client.js
CHANGED
|
@@ -343,6 +343,8 @@ window.__ModuleLoader__.load({
|
|
|
343
343
|
designPlanHint:
|
|
344
344
|
'按官方定价表的模型单价换算本机实际消耗的 Token(不是 usedCredits ÷ 汇率)。Open Design 没有月度用量接口,此值由插件在本机累计观测到的 7 天窗口得出,仅供参考',
|
|
345
345
|
designPlanMultiplier: '按 {multiplier}× 倍率模型计价',
|
|
346
|
+
designPlanWalletShare: '另有 {amount} 由账户余额支付,未计入',
|
|
347
|
+
designPlanPartialPricing: '含未收录价格的模型,金额为下限',
|
|
346
348
|
designPlanComplete: '已覆盖本账期全部窗口',
|
|
347
349
|
designPlanPartial: '仅统计已观测的 {count} 个窗口',
|
|
348
350
|
providerSave: '保存',
|
|
@@ -605,6 +607,8 @@ window.__ModuleLoader__.load({
|
|
|
605
607
|
designPlanHint:
|
|
606
608
|
'Priced from the official per-model rates over the tokens this machine actually consumed (not usedCredits ÷ rate). Open Design serves no period-usage endpoint, so the window total is accumulated locally; treat it as an estimate.',
|
|
607
609
|
designPlanMultiplier: 'priced at the {multiplier}× model rate',
|
|
610
|
+
designPlanWalletShare: 'a further {amount} was paid from the balance and is not counted',
|
|
611
|
+
designPlanPartialPricing: 'includes models with no documented price; the amount is a lower bound',
|
|
608
612
|
designPlanComplete: 'covers every window of this period',
|
|
609
613
|
designPlanPartial: 'only {count} observed window(s)',
|
|
610
614
|
providerConsoleURLPlaceholder: 'Leave empty for the built-in default',
|
|
@@ -1107,6 +1111,12 @@ window.__ModuleLoader__.load({
|
|
|
1107
1111
|
monthlyCapUsd: monthlyCapUsd !== null && monthlyCapUsd > 0 ? monthlyCapUsd : null,
|
|
1108
1112
|
capPercent,
|
|
1109
1113
|
multiplier: multiplier !== null && multiplier > 0 ? multiplier : null,
|
|
1114
|
+
// v1.6.4: the wallet-inclusive local token estimate, shown only as context
|
|
1115
|
+
// next to the Design-Plan-only figure (they differ by wallet-paid calls).
|
|
1116
|
+
localPricedUsd: numberOrNull(raw.localPricedUsd),
|
|
1117
|
+
// v1.6.2: some consumed model had no documented price, so the dollar
|
|
1118
|
+
// figure is a lower bound and must not read as complete.
|
|
1119
|
+
partial: raw.partial === true,
|
|
1110
1120
|
}
|
|
1111
1121
|
}
|
|
1112
1122
|
|
|
@@ -3451,7 +3461,7 @@ window.__ModuleLoader__.load({
|
|
|
3451
3461
|
.dsh-tokenlens-chart-bar-wrap[data-chart-hover=true] .dsh-tokenlens-chart-bar{background:#40c877;filter:brightness(1.12);box-shadow:0 0 0 1px rgba(64,200,119,.55)}
|
|
3452
3462
|
.dsh-tokenlens-chart-crosshair{position:absolute;top:2px;height:160px;z-index:2;pointer-events:none;border-left:1px dashed #d98a1f;opacity:.7}
|
|
3453
3463
|
.dsh-tokenlens-chart-readout{position:absolute;top:4px;z-index:3;pointer-events:none;max-width:calc(100% - 8px);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;border:1px solid var(--dsw-alias-border-subtle,rgba(127,127,127,.3));border-radius:6px;background:var(--dsw-alias-bg-elevated,#202124);color:var(--dsw-alias-label-primary);font-size:11px;line-height:1.4;padding:2px 6px;box-shadow:0 2px 8px rgba(0,0,0,.25);font-variant-numeric:tabular-nums}
|
|
3454
|
-
.dsh-tokenlens-chart-xaxis{position:relative;flex:none;height:14px;min-width:0;max-width:100%;overflow:
|
|
3464
|
+
.dsh-tokenlens-chart-xaxis{position:relative;flex:none;height:14px;min-width:0;max-width:100%;overflow:visible}
|
|
3455
3465
|
.dsh-tokenlens-chart-x-label{position:absolute;top:2px;color:var(--dsw-alias-label-tertiary);font-size:10px;line-height:1.2;white-space:nowrap;font-variant-numeric:tabular-nums}
|
|
3456
3466
|
.dsh-tokenlens-chart-summary{display:flex;flex-wrap:wrap;gap:4px 12px;color:var(--dsw-alias-label-tertiary);font-size:11px;line-height:1.4;min-width:0}
|
|
3457
3467
|
.dsh-tokenlens-chart-summary>span{font-variant-numeric:tabular-nums;overflow-wrap:anywhere}
|
|
@@ -4073,6 +4083,18 @@ window.__ModuleLoader__.load({
|
|
|
4073
4083
|
if (designPlan.multiplier !== null) {
|
|
4074
4084
|
notes.push(t('designPlanMultiplier', { multiplier: designPlan.multiplier }))
|
|
4075
4085
|
}
|
|
4086
|
+
// v1.6.4: when the wallet-inclusive local estimate is HIGHER than the
|
|
4087
|
+
// Design-Plan figure, the difference was paid from the account balance and
|
|
4088
|
+
// must not be presented as Design Plan consumption.
|
|
4089
|
+
if (designPlan.localPricedUsd !== null && designPlan.estimatedUsd !== null) {
|
|
4090
|
+
const walletShare = designPlan.localPricedUsd - designPlan.estimatedUsd
|
|
4091
|
+
if (walletShare > 0.005) {
|
|
4092
|
+
notes.push(t('designPlanWalletShare', { amount: formatMoney(walletShare, 'USD') }))
|
|
4093
|
+
}
|
|
4094
|
+
}
|
|
4095
|
+
// v1.6.2: a model without a documented price makes the figure a lower bound.
|
|
4096
|
+
// Say it rather than letting the number read as complete.
|
|
4097
|
+
if (designPlan.partial === true) notes.push(t('designPlanPartialPricing'))
|
|
4076
4098
|
if (designPlan.complete === true) notes.push(t('designPlanComplete'))
|
|
4077
4099
|
else if (designPlan.windows > 0) notes.push(t('designPlanPartial', { count: designPlan.windows }))
|
|
4078
4100
|
return h(
|
|
@@ -4568,16 +4590,17 @@ window.__ModuleLoader__.load({
|
|
|
4568
4590
|
),
|
|
4569
4591
|
)
|
|
4570
4592
|
const bars = points.map((point, index) => spec.bar(point, index, { max, hovered: index === hoverIndex }))
|
|
4593
|
+
// v1.6.3: centre every label under ITS OWN bar. The bars are a flex row of
|
|
4594
|
+
// equal cells, so bar i is centred at (i + 0.5) / count of the plot width.
|
|
4595
|
+
// The old code pinned the first label to the left edge and the last to the
|
|
4596
|
+
// right edge, which only lines up when the bars fill the whole width: with
|
|
4597
|
+
// 3 bars the first label sat at 0% while its bar was centred at 16.7%, and
|
|
4598
|
+
// the last sat at 100% while its bar was at 83.3% — the dates drifted off
|
|
4599
|
+
// their columns (reported for a 3-day series).
|
|
4571
4600
|
const xLabels = chartXLabelIndices(points.length).map((index) => {
|
|
4572
4601
|
const point = points[index]
|
|
4573
4602
|
const label = spec.xLabel(point, index)
|
|
4574
|
-
const
|
|
4575
|
-
const last = index === points.length - 1
|
|
4576
|
-
const style = first
|
|
4577
|
-
? { left: '0%' }
|
|
4578
|
-
: last
|
|
4579
|
-
? { right: '0%' }
|
|
4580
|
-
: { left: `${((index + 0.5) / points.length) * 100}%`, transform: 'translateX(-50%)' }
|
|
4603
|
+
const style = { left: `${((index + 0.5) / points.length) * 100}%`, transform: 'translateX(-50%)' }
|
|
4581
4604
|
return h(
|
|
4582
4605
|
'span',
|
|
4583
4606
|
{
|
package/index.js
CHANGED
|
@@ -84,7 +84,7 @@ export const inject = []
|
|
|
84
84
|
export const PLUGIN_NAME = 'dsh-tokenlens'
|
|
85
85
|
|
|
86
86
|
/** Plugin version; mirrors package.json (kept here so diagnostics need no fs read). */
|
|
87
|
-
export const PLUGIN_VERSION = '1.6.
|
|
87
|
+
export const PLUGIN_VERSION = '1.6.4'
|
|
88
88
|
|
|
89
89
|
/** Documented defaults; every field of the raw row config is optional. */
|
|
90
90
|
const DEFAULTS = {
|
|
@@ -483,12 +483,16 @@ export function apply(ctx, rawConfig) {
|
|
|
483
483
|
models[modelId] = bucket
|
|
484
484
|
}
|
|
485
485
|
const cost = designPlanCostUsd(models)
|
|
486
|
-
|
|
486
|
+
// v1.6.1: weight the cap by actual per-model consumption, not the worst
|
|
487
|
+
// multiplier. The caps are credit-denominated, so a mostly-0.5x account that
|
|
488
|
+
// touched a 4x model once keeps nearly the full $120.
|
|
489
|
+
const caps = capsForModels(Object.keys(models), cost.mixes)
|
|
487
490
|
return {
|
|
488
491
|
listPriceUsd: cost.priced === true ? cost.usd : null,
|
|
489
492
|
monthlyCapUsd: caps.monthlyCapUsd,
|
|
490
493
|
multiplier: caps.multiplier,
|
|
491
494
|
unpricedModels: cost.unpricedModels,
|
|
495
|
+
partial: cost.unpricedModels.length > 0,
|
|
492
496
|
}
|
|
493
497
|
}
|
|
494
498
|
|
package/lib/design-plan-cost.mjs
CHANGED
|
@@ -73,30 +73,73 @@ export const DESIGN_PLAN_CAPS_USD = { rolling: 10, weekly: 30, monthly: 120 }
|
|
|
73
73
|
* The $120 monthly cap is entirely Design Plan value and is consumed at the
|
|
74
74
|
* model's multiplier, so using ONLY a 0.5x model (DeepSeek V4.1 Flash) unlocks
|
|
75
75
|
* the full $120 of list-price usage; a 1x model reaches $60; 2x reaches $30.
|
|
76
|
-
* With a mixed history the binding constraint is the
|
|
77
|
-
* the
|
|
78
|
-
*
|
|
76
|
+
* With a mixed history the binding constraint is NOT simply the highest
|
|
77
|
+
* multiplier: the caps are denominated in credits (600,000/month at 10,000
|
|
78
|
+
* credits per list-price dollar), and each model burns those credits at its own
|
|
79
|
+
* rate. The account's spendable list-price value is therefore
|
|
79
80
|
*
|
|
81
|
+
* 600,000 credits / m_effective
|
|
82
|
+
*
|
|
83
|
+
* where `m_effective` is the credit-weighted harmonic mean of the multipliers
|
|
84
|
+
* actually used:
|
|
85
|
+
*
|
|
86
|
+
* m_eff = Σ credits_i / Σ (credits_i / m_i), credits_i = listUsd_i × 10000 × m_i
|
|
87
|
+
*
|
|
88
|
+
* Using the plain maximum would understate a mostly-0.5x account that touched a
|
|
89
|
+
* 4x model once: 90% of the credits at 0.5x plus 10% at 4x gives $97.89, not
|
|
90
|
+
* $15. With a single model the formula reduces exactly to that model's
|
|
91
|
+
* documented cap, so the pure cases still match the pricing page.
|
|
92
|
+
*
|
|
93
|
+
* @param modelIds - the model ids in the mix, or
|
|
94
|
+
* @param mixes - a per-model `{ listUsd, multiplier }` split (preferred: it
|
|
95
|
+
* weights by real consumption). `modelIds` is used only when no split is given.
|
|
80
96
|
* @returns `{ monthlyCapUsd, weeklyCapUsd, fiveHourCapUsd, multiplier }` where
|
|
81
|
-
* `multiplier` is the
|
|
82
|
-
*
|
|
97
|
+
* `multiplier` is the effective multiplier, or all-null caps when no model is
|
|
98
|
+
* known.
|
|
83
99
|
*/
|
|
84
|
-
export function capsForModels(modelIds) {
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
100
|
+
export function capsForModels(modelIds, mixes = null) {
|
|
101
|
+
const rows = Array.isArray(mixes)
|
|
102
|
+
? mixes
|
|
103
|
+
.map((mix) => ({
|
|
104
|
+
listUsd: typeof mix?.listUsd === 'number' && Number.isFinite(mix.listUsd) && mix.listUsd > 0 ? mix.listUsd : 0,
|
|
105
|
+
multiplier:
|
|
106
|
+
typeof mix?.multiplier === 'number' && Number.isFinite(mix.multiplier) && mix.multiplier > 0
|
|
107
|
+
? mix.multiplier
|
|
108
|
+
: null,
|
|
109
|
+
}))
|
|
110
|
+
.filter((row) => row.multiplier !== null && row.listUsd > 0)
|
|
111
|
+
: null
|
|
112
|
+
let effective = 0
|
|
113
|
+
if (rows !== null && rows.length > 0) {
|
|
114
|
+
// Credit-weighted harmonic mean (see the doc comment).
|
|
115
|
+
let credits = 0
|
|
116
|
+
let inverse = 0
|
|
117
|
+
for (const row of rows) {
|
|
118
|
+
const rowCredits = row.listUsd * row.multiplier
|
|
119
|
+
credits += rowCredits
|
|
120
|
+
inverse += rowCredits / row.multiplier
|
|
121
|
+
}
|
|
122
|
+
effective = credits > 0 && inverse > 0 ? credits / inverse : 0
|
|
123
|
+
} else {
|
|
124
|
+
// No consumption weighting available: fall back to the highest multiplier,
|
|
125
|
+
// the conservative reading (it promises the LEAST remaining capacity).
|
|
126
|
+
let worst = 0
|
|
127
|
+
for (const id of Array.isArray(modelIds) ? modelIds : []) {
|
|
128
|
+
const model = DESIGN_PLAN_MODELS[normalizeModelId(id)]
|
|
129
|
+
if (model === undefined || !Number.isFinite(model.multiplier) || model.multiplier <= 0) continue
|
|
130
|
+
if (model.multiplier > worst) worst = model.multiplier
|
|
131
|
+
}
|
|
132
|
+
effective = worst
|
|
90
133
|
}
|
|
91
|
-
if (
|
|
134
|
+
if (!(effective > 0)) {
|
|
92
135
|
return { monthlyCapUsd: null, weeklyCapUsd: null, fiveHourCapUsd: null, multiplier: null }
|
|
93
136
|
}
|
|
94
137
|
return {
|
|
95
|
-
// 600,000 credits /
|
|
96
|
-
monthlyCapUsd: 60 /
|
|
97
|
-
weeklyCapUsd: 15 /
|
|
98
|
-
fiveHourCapUsd: 5 /
|
|
99
|
-
multiplier:
|
|
138
|
+
// 600,000 credits / m at 10,000 credits per list-price dollar == $60 / m.
|
|
139
|
+
monthlyCapUsd: 60 / effective,
|
|
140
|
+
weeklyCapUsd: 15 / effective,
|
|
141
|
+
fiveHourCapUsd: 5 / effective,
|
|
142
|
+
multiplier: effective,
|
|
100
143
|
}
|
|
101
144
|
}
|
|
102
145
|
|
|
@@ -153,6 +196,7 @@ export function designPlanCostUsd(models) {
|
|
|
153
196
|
let usd = 0
|
|
154
197
|
let priced = false
|
|
155
198
|
const unpricedModels = []
|
|
199
|
+
const mixes = []
|
|
156
200
|
for (const [modelId, bucket] of Object.entries(models ?? {})) {
|
|
157
201
|
const total = tokens(bucket?.input) + tokens(bucket?.output) + tokens(bucket?.cacheRead) + tokens(bucket?.cacheWrite)
|
|
158
202
|
if (total === 0) continue
|
|
@@ -163,6 +207,11 @@ export function designPlanCostUsd(models) {
|
|
|
163
207
|
}
|
|
164
208
|
usd += cost.usd
|
|
165
209
|
priced = true
|
|
210
|
+
// Per-model list-price spend, so the cap can be weighted by real consumption.
|
|
211
|
+
const model = designPlanModel(modelId)
|
|
212
|
+
if (model !== null && Number.isFinite(model.multiplier) && model.multiplier > 0 && cost.usd > 0) {
|
|
213
|
+
mixes.push({ modelId: normalizeModelId(modelId), listUsd: cost.usd, multiplier: model.multiplier })
|
|
214
|
+
}
|
|
166
215
|
}
|
|
167
|
-
return { usd, priced, unpricedModels }
|
|
216
|
+
return { usd, priced, unpricedModels, mixes }
|
|
168
217
|
}
|
|
@@ -266,18 +266,34 @@ export function summarizeDesignPlan(ledger, periodStart, input = null) {
|
|
|
266
266
|
windows += 1
|
|
267
267
|
}
|
|
268
268
|
const creditsPerUsd = period.creditsPerUsd
|
|
269
|
-
// v1.6.0: `creditsPerUsd` conversion is kept ONLY as a fallback. It assumes the
|
|
270
|
-
// account burns credits at 1x, but the documented multipliers range 0.25x–4x,
|
|
271
|
-
// so it is wrong for any non-1x model (2x too low for DeepSeek V4.1 Flash).
|
|
272
|
-
// The caller passes the documented list-price cost instead.
|
|
273
269
|
const creditsUsd =
|
|
274
270
|
Number.isSafeInteger(creditsPerUsd) && creditsPerUsd > 0 ? usedCredits / creditsPerUsd : null
|
|
275
|
-
const
|
|
271
|
+
const multiplier = Number.isFinite(input?.multiplier) && input.multiplier > 0 ? input.multiplier : null
|
|
272
|
+
// v1.6.4: the Design Plan figure is derived FROM THE SERVER'S credits, not from
|
|
273
|
+
// locally-priced tokens. This is what makes it a Design-Plan-only number:
|
|
274
|
+
// credits are deducted for Design Plan allowance ONLY.
|
|
275
|
+
// Wallet-funded usage never touches them — it debits `balanceUsd` instead.
|
|
276
|
+
//
|
|
277
|
+
// `usedCredits / creditsPerUsd` yields the *credit* value; the documented list
|
|
278
|
+
// price is that divided by the model multiplier, because a 0.5x model burns
|
|
279
|
+
// half a credit per list-price dollar. Verified against the account's own caps:
|
|
280
|
+
// 149,932 credits / 10,000 / 0.5 = $29.99
|
|
281
|
+
// 30 * (149,932 / 150,000) = $29.99 (the 7-day cap is $30)
|
|
282
|
+
// Both agree, which is the cross-check that the formula is right.
|
|
283
|
+
//
|
|
284
|
+
// The locally-priced token total (input.listPriceUsd) is kept as `walletUsd`
|
|
285
|
+
// context: it includes wallet-funded calls, so it can EXCEED this figure. It is
|
|
286
|
+
// reported separately and never mixed into `estimatedUsd`.
|
|
287
|
+
const designPlanUsd =
|
|
288
|
+
creditsUsd === null ? null : multiplier === null ? creditsUsd : creditsUsd / multiplier
|
|
289
|
+
const estimatedUsd = designPlanUsd !== null ? designPlanUsd : Number.isFinite(input?.listPriceUsd) ? input.listPriceUsd : null
|
|
276
290
|
const since = entries[0][0]
|
|
277
291
|
const limitPerWindow = entries[entries.length - 1][1].limitCredits
|
|
278
292
|
const usableWindowLimit = Number.isSafeInteger(limitPerWindow) && limitPerWindow > 0 ? limitPerWindow : null
|
|
279
293
|
const periodLimitCredits = usableWindowLimit === null ? null : usableWindowLimit * WEEKS_PER_PERIOD
|
|
280
294
|
const percent = periodLimitCredits === null ? null : (usedCredits / periodLimitCredits) * 100
|
|
295
|
+
// The cap is a list-price cap for the model mix, so compare it against the
|
|
296
|
+
// list-price figure derived from credits.
|
|
281
297
|
const monthlyCapUsd = Number.isFinite(input?.monthlyCapUsd) ? input.monthlyCapUsd : null
|
|
282
298
|
const capPercent =
|
|
283
299
|
estimatedUsd !== null && monthlyCapUsd !== null && monthlyCapUsd > 0
|
|
@@ -287,11 +303,17 @@ export function summarizeDesignPlan(ledger, periodStart, input = null) {
|
|
|
287
303
|
periodStart: key,
|
|
288
304
|
periodEnd: period.periodEnd || '',
|
|
289
305
|
usedCredits,
|
|
306
|
+
// Design-Plan-only dollars (from server credits). Comparable with the caps.
|
|
290
307
|
estimatedUsd,
|
|
308
|
+
// The wallet-inclusive local estimate, kept for transparency/contrast only.
|
|
309
|
+
localPricedUsd: Number.isFinite(input?.listPriceUsd) ? input.listPriceUsd : null,
|
|
291
310
|
creditsUsd,
|
|
292
311
|
monthlyCapUsd,
|
|
293
|
-
multiplier
|
|
312
|
+
multiplier,
|
|
294
313
|
capPercent,
|
|
314
|
+
// v1.6.2: true when some consumed model has no documented price, so
|
|
315
|
+
// `estimatedUsd` is a lower bound and the UI must say so.
|
|
316
|
+
partial: input?.partial === true,
|
|
295
317
|
windows,
|
|
296
318
|
complete: since === key,
|
|
297
319
|
since,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-tokenlens",
|
|
3
|
-
"version": "1.6.
|
|
3
|
+
"version": "1.6.4",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "dsh-TokenLens (词元透镜) — provider-aware plan capacity plus local token statistics (today/7d/30d/all-time, by harness/provider/model/workspace) for DSH.",
|
|
6
6
|
"license": "MIT",
|