dsh-tokenlens 1.6.5 → 1.6.7
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 +16 -2
- package/PROTOCOL.md +30 -1
- package/README.en.md +2 -2
- package/README.md +5 -4
- package/index.js +1 -1
- package/lib/providers.mjs +86 -16
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -4,9 +4,23 @@
|
|
|
4
4
|
|
|
5
5
|
**版本记录约定**:同一发布日只保留一个章节,标题取当日**最后一个**已发布版本号;当日多次发布的改动合并到该章节,并在标题下注明当日实际发布过的版本号(npm 上仍可安装这些独立版本)。若当日已有发布,后续小改动不再单独增加版本号,而是并入下一篇日志。这样日志按天规整、不出现同日多个小版本。
|
|
6
6
|
|
|
7
|
-
## 1.6.
|
|
7
|
+
## 1.6.7 — 2026-11-05
|
|
8
8
|
|
|
9
|
-
(当日已发布版本:v1.6.5
|
|
9
|
+
(当日已发布版本:v1.6.5 / v1.6.6 / v1.6.7)
|
|
10
|
+
|
|
11
|
+
- **fix(commandcode): 用实时窗口用量校正滞后的 `usage summary`**——`/alpha/usage/summary` 是聚合接口,比滚动窗口**滞后几美分**(实测 summary `$1.1248` vs 实时 `$1.2802`),直接拿它反推会让额度偏小、百分比偏低约 0.2 个百分点。现在取「summary 与实时窗口用量」中的**最大值**作为本期消费下界——summary 提供锚点,实时窗口只会把估计值推向真值。实测修正后月额度精确回到 **$70.00**、百分比 `1.85%`,与该平台控制台一致
|
|
12
|
+
- fix(commandcode): **仅在 summary 存在时才用窗口用量校正**——没有 summary 就没有锚点,此时周窗口可能并不覆盖整个账期,用它反推会把额度放大、百分比压向 0,因此该情况仍保持 `null`
|
|
13
|
+
|
|
14
|
+
### v1.6.6 同日内容
|
|
15
|
+
|
|
16
|
+
- **feat(commandcode): 补上月用量百分比**——该平台付费套餐**不下发** `monthlyCreditsGranted`(额度分母),此前月窗口只能是 `unknown`。现在同时读 `GET /alpha/usage/summary`(控制台自己用的那个接口),用两个字段反推额度:`grant = credits.monthlyCredits(余额)+ totalMonthlyCredits(本期消费)`。实测 `69.1272003646 + 0.8727996354 = 70.0000000000`(多时点复核均精确 70),与控制台前端内置的 `totalCredits: 70` 一致
|
|
17
|
+
- feat(commandcode): 月窗口因此同时具备**已用 / 额度 / 百分比 / 重置时间**(`$0.99 / $70.00 · 1.4%`),与 5 小时、每周两个窗口口径一致
|
|
18
|
+
- **fix(commandcode): 不再把 `windowLimits.limited` 当作告警状态**——它是「本套餐带滚动窗口限制」的**能力标志**,同层另有 `exceeded`。原来映射成 `status: "limited"`,而客户端把任何非 `ok` 状态渲染为告警,导致用量仅 6% 时三个窗口全被涂成红色。现在只有各窗口 `exceeded === true` 才置为非 `ok`,其余按百分比自身分级
|
|
19
|
+
- feat(commandcode): 套餐名映射补全 `individual-goat → GOAT`、`individual-pro/v1 → Pro`、`individual-max → Max`、`individual-ultra → Ultra`(此前 GOAT 直接显示原始 id)
|
|
20
|
+
- **口径说明**:月额度分母**不随所选模型变化**。GOAT 宣传「Up to $100」并给出按模型额度(DeepSeek V4.1 Flash 为 $100),那是同一份额度在折价模型上的「等效可用金额」,额度池始终是 `totalCredits: 70` 这一个数。若让分母跟随所选模型,切换模型时百分比会跳动而账户并未变化,故按固定池计算
|
|
21
|
+
- 测试:352 → 355(月额度反推、分母不随模型变化、已上报额度优先于反推、`limited` 是能力标志而非状态、月窗口渲染与配色)
|
|
22
|
+
|
|
23
|
+
### v1.6.5 同日内容(修复 GitHub issue #1)
|
|
10
24
|
|
|
11
25
|
- **fix(ui): 没有额度适配器的供应商不再隐藏芯片**——`unsupported-provider` 按协议会静默隐藏芯片,但芯片同时是**本机 Token 统计的唯一入口**,于是「有数据却永远看不到」:选中 `xiaomi-token-plan-cn` 时 `usage-cache.json` 里躺着 3.19 亿 Token 却无处可查(issue #1 的核心投诉)。现在这类供应商保留一个「**仅本机统计**」芯片(圆点为正常态而非告警),点开即见统计区——统计区本就不依赖快照
|
|
12
26
|
- **feat(providers): 新增小米 MiMo「Token Plan」额度适配器**(`xiaomi-token-plan-cn` / `-ams` / `-sgp` 三个区域)——额度接口在控制台域 `platform.xiaomimimo.com`:`/api/v1/tokenPlan/usage`(`plan_total_token` 与 `monthUsage`)、`/api/v1/tokenPlan/detail`(`planCode`、`currentPeriodEnd`)、`/api/v1/balance`(人民币余额)
|
package/PROTOCOL.md
CHANGED
|
@@ -101,7 +101,7 @@ Provider semantics:
|
|
|
101
101
|
| provider id | kind | windows | extra |
|
|
102
102
|
|---|---|---|---|
|
|
103
103
|
| `opencode-go` | `windows` | rolling/weekly/monthly percentages | — |
|
|
104
|
-
| `commandcode` | `windows` | rolling = 5-hour `used/cap`, weekly = `used/cap`, monthly = `
|
|
104
|
+
| `commandcode` | `windows` | rolling = 5-hour `used/cap`, weekly = `used/cap`, monthly = `used/granted` where `granted` is the API-reported grant, else `credits.monthlyCredits + /alpha/usage/summary.totalMonthlyCredits` (v1.6.6) | `plan`, `credits` (USD), `account` |
|
|
105
105
|
| `deepseek` (picker id `deepseek-official`) | `balance` | `null` | `balance` (API-key account balance, CNY/USD) |
|
|
106
106
|
| `deepseek-account` | `balance` | `null` | `balance` from the composed Platform account service (signed-in wallets) |
|
|
107
107
|
| `open-design` | `windows` | rolling = 5-hour Design Plan window, weekly = 7-day window, monthly = 30-day window when reported (used / limit credits, capped at 100%) | `balance` (independent wallet balance, USD) |
|
|
@@ -109,6 +109,35 @@ Provider semantics:
|
|
|
109
109
|
`balance` is `{ amount, currency }` plus, for the account provider,
|
|
110
110
|
`wallets: [{currency, amount}]` and `bonus: [{currency, amount}]`.
|
|
111
111
|
|
|
112
|
+
### Command Code's monthly percentage (v1.6.6)
|
|
113
|
+
|
|
114
|
+
`commandcode` reads four routes: `/alpha/billing/credits`, `/alpha/billing/subscriptions`,
|
|
115
|
+
`/alpha/whoami`, and `/alpha/usage/summary` — the last one is the aggregate the provider's
|
|
116
|
+
own console renders, and it is what makes the monthly percentage computable, because a paid
|
|
117
|
+
plan does **not** send `monthlyCreditsGranted`:
|
|
118
|
+
|
|
119
|
+
```
|
|
120
|
+
granted = credits.monthlyCredits (remaining) + usage.totalMonthlyCredits (period spend)
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
Verified live on `individual-goat`: `69.1272003646 + 0.8727996354 = 70.0000000000`, and the
|
|
124
|
+
console's own bundle declares `totalCredits: 70` for that plan. The only imprecision is that
|
|
125
|
+
`/alpha/usage/summary` lags by a fraction of a cent, so the derived grant can read ~$0.003
|
|
126
|
+
under the pool for a moment; it self-corrects on the next poll. A reported grant always wins
|
|
127
|
+
over the derivation, and when neither is available the monthly `percent` stays `null` — the
|
|
128
|
+
plugin never sizes a month from a plan catalog.
|
|
129
|
+
|
|
130
|
+
**The denominator is deliberately model-independent.** GOAT advertises "up to $100" and lists
|
|
131
|
+
per-model allowances ($100 on DeepSeek V4.1 Flash, $60 on several others) because the same
|
|
132
|
+
credits stretch further on a discounted model; the pool itself is one number. Letting the
|
|
133
|
+
picker change the denominator would move the meter while the account did not change, so
|
|
134
|
+
`parseCommandCode` takes no model input.
|
|
135
|
+
|
|
136
|
+
`windowLimits.limited` is a **capability flag** ("this plan paces you with rolling windows"),
|
|
137
|
+
not a state: the live payload carries `limited: true` together with `fiveHour.exceeded: false`.
|
|
138
|
+
Only a per-window `exceeded === true` produces a non-`ok` status, because the client renders
|
|
139
|
+
any other status as an alert (which made a 6%-used account look critical before v1.6.6).
|
|
140
|
+
|
|
112
141
|
A `windows` snapshot may also carry a non-null `balance` (Open Design reports
|
|
113
142
|
allowance windows and a wallet independently); the Client renders it as one extra
|
|
114
143
|
row at the end of the capacity card and appends the amount to the chip tooltip.
|
package/README.en.md
CHANGED
|
@@ -136,7 +136,7 @@ Host bridge route: `/api/tokenlens`; agent tool: `tokenlens_usage`.
|
|
|
136
136
|
## Limitations
|
|
137
137
|
|
|
138
138
|
- Provider usage endpoints are mostly private / undocumented and may change at any time; the plugin degrades gracefully (retryable errors, hidden chips, per-row fallbacks) but availability is not guaranteed.
|
|
139
|
-
- Plan capacity shows native server values only: no token → money conversion
|
|
139
|
+
- Plan capacity shows native server values only: no token → money conversion. Command Code's monthly percentage (v1.6.6) derives the grant as `credits.monthlyCredits + /alpha/usage/summary.totalMonthlyCredits` when the plan reports none; the denominator is the fixed plan pool and deliberately does **not** follow the selected model.
|
|
140
140
|
- "Estimated consumable" is derived from local tokens and the plan percentage; it is only a hint, not a provider commitment.
|
|
141
141
|
- The startup update check is on by default (switchable off) and compares the **latest npm release** only; commits on the GitHub repository are not detected — a git-installed plugin must be uninstalled and reinstalled to update.
|
|
142
142
|
- Local stats cover connected harnesses on this machine only; uninstalled harnesses are hidden by default (`stats.showUninstalled: true` shows them). Workspace token badges are experimental.
|
|
@@ -144,7 +144,7 @@ Host bridge route: `/api/tokenlens`; agent tool: `tokenlens_usage`.
|
|
|
144
144
|
|
|
145
145
|
## Development
|
|
146
146
|
|
|
147
|
-
Node.js ≥ 24, zero runtime dependencies: `node --test` runs the
|
|
147
|
+
Node.js ≥ 24, zero runtime dependencies: `node --test` runs the 357 tests.
|
|
148
148
|
|
|
149
149
|
Release: `node scripts/bump-version.mjs <version> "<note>"` updates `package.json`, `PLUGIN_VERSION` and `CHANGELOG.md`; see [CONTRIBUTING.md](CONTRIBUTING.md) and [SECURITY.md](SECURITY.md).
|
|
150
150
|
|
package/README.md
CHANGED
|
@@ -308,7 +308,7 @@ Control Key 是 **Open Design 桌面端/CLI 登录时写入本机的会话凭据
|
|
|
308
308
|
| 供应商 | 数据来源(Key 或服务) | 展示 |
|
|
309
309
|
|---|---|---|
|
|
310
310
|
| `opencode-go` / `opencode` | `GET https://opencode.ai/inference/go/v1/usage`(`OPENCODE_GO_API_KEY`) | 5 小时 / 本周 / 本月 已用百分比 + 重置时间 |
|
|
311
|
-
| `commandcode` | `api.commandcode.ai/alpha/billing/{credits,subscriptions}` + `/alpha/whoami`(`COMMANDCODE_API_KEY`) | 5 小时 / 每周 `$已用 /
|
|
311
|
+
| `commandcode` | `api.commandcode.ai/alpha/billing/{credits,subscriptions}` + `/alpha/whoami` + `/alpha/usage/summary`(`COMMANDCODE_API_KEY`) | 5 小时 / 每周 `$已用 / $上限`;月度 `$已用 / $额度 · %`(v1.6.6);方案名 |
|
|
312
312
|
| `deepseek`(选择器里的 `deepseek-official`) | `GET https://api.deepseek.com/user/balance`(`DEEPSEEK_API_KEY`) | 账户余额 |
|
|
313
313
|
| `deepseek-account` | DSH 组合内的 `deepseekAccount` 服务 | 钱包余额(含赠送) |
|
|
314
314
|
| `openrouter` | `GET https://openrouter.ai/api/v1/credits`(管理 Key;普通 Key 可用 `/api/v1/key`) | 剩余额度(USD) |
|
|
@@ -326,7 +326,8 @@ Control Key 是 **Open Design 桌面端/CLI 登录时写入本机的会话凭据
|
|
|
326
326
|
| `xiaomi-token-plan-cn` / `-ams` / `-sgp` | 控制台额度接口:`GET https://platform.xiaomimimo.com/api/v1/tokenPlan/usage` + `/tokenPlan/detail`(周期结束时间、方案码)+ `/api/v1/balance`(人民币余额)。**只认控制台 Cookie**(`XIAOMI_MIMO_COOKIE`),推理 Key 一律 401 | Token Plan 的每月 已用百分比 + 重置时间;方案码;账户余额(CNY) |
|
|
327
327
|
|
|
328
328
|
- OpenCode 的额度定义见[官方文档](https://opencode.ai/docs/go/#usage-limits)(5h = 月度额度的 20%、周 = 50%、月 = 100%);接口只返回百分比,插件也只画百分比。
|
|
329
|
-
- Command Code 的 `/alpha/*` 是官方 CLI 自用的私有计费路由;免费 / 无方案账户返回空窗口(显示
|
|
329
|
+
- Command Code 的 `/alpha/*` 是官方 CLI 自用的私有计费路由;免费 / 无方案账户返回空窗口(显示 `—`),插件不会用方案目录猜额度。**月度百分比**(v1.6.6)在套餐不下发额度时由 `credits.monthlyCredits(余额)+ /alpha/usage/summary 的 totalMonthlyCredits(本期消费)` 反推额度后计算,实测与该平台控制台一致;分母是**固定的额度池,不随所选模型变化**——GOAT 宣传的「Up to $100」与按模型额度(DeepSeek V4.1 Flash $100)只是同一份额度在折价模型上的等效值,若让分母跟随模型,切换模型时百分比会跳动而账户未变。
|
|
330
|
+
- **「有限额」不等于「已超限」**(v1.6.6)。Command Code 的 `windowLimits.limited` 是「本套餐带滚动窗口」的能力标志,真正的状态在同层 `exceeded`;插件此前把它当状态输出,会让用量仅 6% 的三个窗口全被涂成告警色,现已只有 `exceeded === true` 才告警。
|
|
330
331
|
- Open Design 的窗口按账户实际返回的时长渲染:Go 同时有 5 小时和 7 天窗口,Plus / Pro / Max 只有 7 天窗口;钱包余额是独立于窗口的 USD 额度,用尽后继续扣钱包。查询要求工作区权限,鉴权失败会明确显示错误而不是 0。**只需填一个 Control Key**:工作区 ID 是可选项(v1.5.3),插件会用 Key 调 `/api/v1/workspaces/current` 自动识别你的工作区;只有账号有多个工作区、需要指定其中一个时才在管理页填「工作区 ID」。真正缺 Key 时弹窗会指出并给出「去配置」入口。窗口、余额、套餐档位是**三层独立读取**(v1.4.0):任一接口不可用时只少那一块数据,不会整套报错。
|
|
331
332
|
- **chip 的「月 N%」与「本期 Design Plan 累计」是插件本机算的估算值**(v1.5.0 / v1.6.0)。Open Design 有月度额度(Go 为每月 $120 = 4 × 每周 $30),但**没有「本账期已用」接口**——控制台的 `/billing/usage`、`/billing/coding-plan-usage` 都靠浏览器 Cookie 鉴权,Control Key 一律 401。于是插件累加它观测到的 **7 天窗口**(只记 7 天,因为 5 小时窗口测量的是同一笔消耗,相加会重复计数)。
|
|
332
333
|
- **金额按服务端 credits 反推,只统计 Design Plan 额度消耗**(v1.6.4)。钱包扣费不消耗 credits,只扣 `balanceUsd`,所以「本期 Design Plan 累计」= `usedCredits ÷ creditsPerUsd ÷ 倍率`——实测 `150,005 ÷ 10,000 ÷ 0.5 = $30.00`,与「周额度 $30 × 已用 100%」交叉验证一致。含钱包付费的本机估算另存为 `localPricedUsd`,高于前者时弹窗追加「另有 $X 由账户余额支付,未计入」,两个口径都清楚可查。
|
|
@@ -430,7 +431,7 @@ Host 半注册 `tokenlens_usage`,参数 `action`(默认 `snapshot`)与可
|
|
|
430
431
|
## 已知限制
|
|
431
432
|
|
|
432
433
|
- 各供应商的用量接口多为**未公开的私有接口**,可能随时变更;插件对此做了优雅降级(可重试错误、静默隐藏、行级降级),但不保证长期可用。
|
|
433
|
-
- 套餐容量只显示服务端原生数字:不做 token → 金额换算;Command Code
|
|
434
|
+
- 套餐容量只显示服务端原生数字:不做 token → 金额换算;Command Code 的月度百分比由「余额 + 本期消费」反推额度后计算(v1.6.6),两者都拿不到时才留空。
|
|
434
435
|
- 「预计可消耗」是基于本机 Token 与套餐百分比的**估算**,仅供参考,不代表供应商承诺的额度。
|
|
435
436
|
- 「启动时检查更新」默认开启(可在插件设置关闭),只对比 **npm 上的最新发布版本**;GitHub 仓库的提交更新不会被感知,需要卸载重装 git 安装的版本才会更新。
|
|
436
437
|
- 本机 Token 统计只覆盖**已接入 harness**(当前 DSH / ZCode / OpenCode CLI / WorkBuddy / Qoder CN),只统计本机的本地记录。
|
|
@@ -444,7 +445,7 @@ Host 半注册 `tokenlens_usage`,参数 `action`(默认 `snapshot`)与可
|
|
|
444
445
|
|
|
445
446
|
## 验证
|
|
446
447
|
|
|
447
|
-
- `node --test`:**
|
|
448
|
+
- `node --test`:**357 个自动化用例**,覆盖 Host 数据层、供应商适配器(含小米 MiMo 控制台 Cookie 适配器、Command Code 月度额度反推)、统计折叠、各 harness 读取、Design Plan 周期账本与额度计价、窗口锚点切片、工作区自动识别、插件集成与浏览器端渲染 / 交互。
|
|
448
449
|
- 在真实环境中验证过 **5 个 harness** 的数据源;本机统计与独立的 SQLite 查询、独立的日志解析逐项对账(差额为 0),跨 harness 合并与供应商映射算术自洽。
|
|
449
450
|
- 供应商接口按各官方文档与参考客户端行为验证;未配置凭据时 chip 静默隐藏,接口异常时按可重试错误降级。
|
|
450
451
|
|
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.7'
|
|
88
88
|
|
|
89
89
|
/** Documented defaults; every field of the raw row config is optional. */
|
|
90
90
|
const DEFAULTS = {
|
package/lib/providers.mjs
CHANGED
|
@@ -85,6 +85,10 @@ export const PROVIDER_DEFAULTS = {
|
|
|
85
85
|
creditsPath: '/alpha/billing/credits',
|
|
86
86
|
subscriptionsPath: '/alpha/billing/subscriptions',
|
|
87
87
|
whoamiPath: '/alpha/whoami',
|
|
88
|
+
// v1.6.6: the console's own usage aggregate. Carries `totalMonthlyCredits`,
|
|
89
|
+
// the period spend the monthly percentage needs (the credits route has no
|
|
90
|
+
// grant field on a paid plan).
|
|
91
|
+
usageSummaryPath: '/alpha/usage/summary',
|
|
88
92
|
apiKeyRef: 'COMMANDCODE_API_KEY',
|
|
89
93
|
consoleUrl: 'https://commandcode.ai/',
|
|
90
94
|
},
|
|
@@ -371,6 +375,11 @@ export function canonicalProviderId(providerId) {
|
|
|
371
375
|
const COMMANDCODE_PLAN_LABELS = {
|
|
372
376
|
'individual-go-v1': 'Go',
|
|
373
377
|
'individual-go': 'Go',
|
|
378
|
+
'individual-goat': 'GOAT',
|
|
379
|
+
'individual-pro': 'Pro',
|
|
380
|
+
'individual-pro-v1': 'Pro',
|
|
381
|
+
'individual-max': 'Max',
|
|
382
|
+
'individual-ultra': 'Ultra',
|
|
374
383
|
}
|
|
375
384
|
|
|
376
385
|
/** A friendly plan label for a Command Code plan id (raw id when unknown). */
|
|
@@ -467,31 +476,42 @@ export function parseOpencodeGo(payload, now = Date.now()) {
|
|
|
467
476
|
* windowLimits: { limited, fiveHour: {cap,used,resetAt}|null, weekly: … } }`
|
|
468
477
|
* `subscription`: `{ success, data: { planId, status, currentPeriodEnd }|null }`
|
|
469
478
|
* `whoami`: `{ success, user: { name, userName } }`
|
|
479
|
+
* `usageSummary` (v1.6.6): `GET /alpha/usage/summary` —
|
|
480
|
+
* `{ totalMonthlyCredits, totalCredits, periodBasis, periodStart, … }`. Its
|
|
481
|
+
* `totalMonthlyCredits` is what makes the MONTHLY percentage computable.
|
|
470
482
|
*
|
|
471
483
|
* Semantics verified against the live API and the CodexBar reference client:
|
|
472
|
-
* `monthlyCredits` is the REMAINING monthly credit (USD), `
|
|
473
|
-
* plan's monthly grant
|
|
474
|
-
*
|
|
484
|
+
* `monthlyCredits` is the REMAINING monthly credit (USD), `monthlyCreditsGranted`
|
|
485
|
+
* is the plan's monthly grant when present (a paid GOAT plan omits it, which is
|
|
486
|
+
* why `usageSummary` is consulted); the windows' `used`/`cap` are USD, `resetAt`
|
|
487
|
+
* is epoch seconds or milliseconds.
|
|
475
488
|
*/
|
|
476
|
-
export function parseCommandCode({ credits, subscription, whoami } = {}, now = Date.now()) {
|
|
489
|
+
export function parseCommandCode({ credits, subscription, whoami, usageSummary } = {}, now = Date.now()) {
|
|
477
490
|
const document = credits !== null && typeof credits === 'object' ? credits : {}
|
|
478
491
|
const credit = document.credits !== null && typeof document.credits === 'object' ? document.credits : {}
|
|
479
492
|
const limits = document.windowLimits !== null && typeof document.windowLimits === 'object'
|
|
480
493
|
? document.windowLimits
|
|
481
494
|
: {}
|
|
482
|
-
|
|
483
|
-
|
|
495
|
+
// v1.6.6: `windowLimits.limited` is a CAPABILITY flag ("this plan paces you
|
|
496
|
+
// with rolling windows"), not a state — the live GOAT payload carries
|
|
497
|
+
// `limited: true` while every `fiveHour.exceeded` / `weekly.exceeded` is false.
|
|
498
|
+
// Mapping it onto `status` painted every window as a warning (PROTOCOL: any
|
|
499
|
+
// status that is not "ok" renders as an alert), so a 6%-used account looked
|
|
500
|
+
// alarming. The real state lives in the per-window `exceeded` flags.
|
|
501
|
+
const planExceeded = limits.exceeded === true
|
|
484
502
|
const windowFrom = (raw) => {
|
|
485
503
|
if (raw === null || typeof raw !== 'object') return null
|
|
504
|
+
const exceeded = raw.exceeded === true
|
|
486
505
|
return {
|
|
487
506
|
percent: usedPercent(raw.used, raw.cap),
|
|
488
|
-
status:
|
|
507
|
+
status: exceeded ? 'limited' : 'ok',
|
|
489
508
|
resetsAt: raw.resetAt,
|
|
490
509
|
used: toNumber(raw.used),
|
|
491
510
|
cap: toNumber(raw.cap),
|
|
492
511
|
unit: 'USD',
|
|
493
512
|
}
|
|
494
513
|
}
|
|
514
|
+
const anyExceeded = () => planExceeded
|
|
495
515
|
const windows = windowSet(
|
|
496
516
|
{ rolling: windowFrom(limits.fiveHour), weekly: windowFrom(limits.weekly) },
|
|
497
517
|
now,
|
|
@@ -504,21 +524,65 @@ export function parseCommandCode({ credits, subscription, whoami } = {}, now = D
|
|
|
504
524
|
const plan = planId === null ? null : { id: planId, label: commandcodePlanLabel(planId) }
|
|
505
525
|
|
|
506
526
|
const remaining = toNumber(credit.monthlyCredits)
|
|
507
|
-
// Only the API-reported grant sizes the monthly percentage: this plugin never
|
|
508
|
-
// guesses a grant from a plan catalog (the live free-tier response omits it).
|
|
509
|
-
const granted = toNumber(credit.monthlyCreditsGranted)
|
|
510
527
|
const purchased = toNumber(credit.purchasedCredits)
|
|
528
|
+
// v1.6.6: the monthly percentage.
|
|
529
|
+
//
|
|
530
|
+
// `/alpha/billing/credits` does NOT send a grant (`monthlyCreditsGranted` is
|
|
531
|
+
// simply absent on a paid plan), but two API fields together pin it down:
|
|
532
|
+
// `credits.monthlyCredits` is the pool REMAINING and
|
|
533
|
+
// `/alpha/usage/summary`'s `totalMonthlyCredits` is the period's SPEND:
|
|
534
|
+
//
|
|
535
|
+
// grant = remaining + periodSpend
|
|
536
|
+
//
|
|
537
|
+
// Verified live on `individual-goat` at several moments:
|
|
538
|
+
// 69.1272003646 + 0.8727996354 = 70.0000000000
|
|
539
|
+
// 69.1568775436 + 0.8431224564 = 70.0000000000
|
|
540
|
+
// 69.085104928 + 0.9119659668 = 69.99707 (summary lags a fraction)
|
|
541
|
+
// and the console's own plan catalog declares `totalCredits: 70` for GOAT, so
|
|
542
|
+
// the derivation is not a guess.
|
|
543
|
+
//
|
|
544
|
+
// The denominator is deliberately MODEL-INDEPENDENT. GOAT advertises "up to
|
|
545
|
+
// $100 in credits" and shows per-model allowances ($100 on DeepSeek V4.1 Flash,
|
|
546
|
+
// $60 on others) because the same credits stretch further on a discounted
|
|
547
|
+
// model — but the pool itself stays one number whatever model is selected
|
|
548
|
+
// (hence "up to"). Letting the picker change the denominator would make the
|
|
549
|
+
// meter jump while the account did not move, so it never does that here.
|
|
550
|
+
const summary = usageSummary !== null && typeof usageSummary === 'object' ? usageSummary : {}
|
|
551
|
+
const periodSpend = toNumber(summary.totalMonthlyCredits) ?? toNumber(summary.totalCredits)
|
|
552
|
+
// `/alpha/usage/summary` is an aggregate and LAGS the live windows by up to a
|
|
553
|
+
// few cents (observed $1.12 vs $1.28 live), which would understate the derived
|
|
554
|
+
// grant and therefore the percentage. When the summary is present it anchors
|
|
555
|
+
// the period, and a rolling window's `used` — always a subset of the period —
|
|
556
|
+
// can then only raise the estimate towards the truth, so the largest of them is
|
|
557
|
+
// taken. WITHOUT the summary the windows are NOT usable this way: a weekly
|
|
558
|
+
// window that does not cover the whole period would inflate the grant and drive
|
|
559
|
+
// the percentage towards zero, so that case stays `null`.
|
|
560
|
+
const liveWindowSpend =
|
|
561
|
+
periodSpend === null
|
|
562
|
+
? []
|
|
563
|
+
: [toNumber(limits.fiveHour?.used), toNumber(limits.weekly?.used)].filter((value) => value !== null)
|
|
564
|
+
const spend = periodSpend === null ? null : Math.max(periodSpend, ...liveWindowSpend)
|
|
565
|
+
const reportedGrant = toNumber(credit.monthlyCreditsGranted)
|
|
566
|
+
const granted =
|
|
567
|
+
reportedGrant !== null && reportedGrant > 0
|
|
568
|
+
? reportedGrant
|
|
569
|
+
: remaining !== null && spend !== null
|
|
570
|
+
? remaining + spend
|
|
571
|
+
: null
|
|
572
|
+
const monthlyUsed = granted !== null && remaining !== null ? Math.max(0, granted - remaining) : spend
|
|
511
573
|
const monthlyPercent =
|
|
512
|
-
|
|
513
|
-
? normalizePercent((
|
|
574
|
+
granted !== null && granted > 0 && monthlyUsed !== null
|
|
575
|
+
? normalizePercent((monthlyUsed / granted) * 100)
|
|
514
576
|
: null
|
|
515
577
|
windows.monthly = makeWindow(
|
|
516
578
|
'monthly',
|
|
517
579
|
{
|
|
518
580
|
percent: monthlyPercent,
|
|
519
|
-
|
|
581
|
+
// Same rule as the rolling windows: only a real exhaustion is a status, and
|
|
582
|
+
// the percentage itself already drives the warning/critical colour.
|
|
583
|
+
status: monthlyPercent === null ? 'unknown' : anyExceeded() ? 'limited' : 'ok',
|
|
520
584
|
resetsAt: data?.currentPeriodEnd ?? null,
|
|
521
|
-
used:
|
|
585
|
+
used: monthlyUsed,
|
|
522
586
|
cap: granted,
|
|
523
587
|
unit: 'USD',
|
|
524
588
|
},
|
|
@@ -1321,11 +1385,17 @@ export const ADAPTERS = {
|
|
|
1321
1385
|
async read({ providerId = 'commandcode', provider, fetchJson, now }) {
|
|
1322
1386
|
const config = providerConfig(providerId, provider)
|
|
1323
1387
|
const credits = await fetchJson(joinUrl(config.baseURL, config.creditsPath))
|
|
1324
|
-
|
|
1388
|
+
// v1.6.6: the usage aggregate is what makes the monthly percentage
|
|
1389
|
+
// computable, but it is not essential to the rest of the read — a failure
|
|
1390
|
+
// only costs that one number, so it is tolerated like subscriptions/whoami.
|
|
1391
|
+
const [subscription, whoami, usageSummary] = await Promise.all([
|
|
1325
1392
|
fetchJson(joinUrl(config.baseURL, config.subscriptionsPath)).catch(() => undefined),
|
|
1326
1393
|
fetchJson(joinUrl(config.baseURL, config.whoamiPath)).catch(() => undefined),
|
|
1394
|
+
config.usageSummaryPath === undefined
|
|
1395
|
+
? undefined
|
|
1396
|
+
: fetchJson(joinUrl(config.baseURL, config.usageSummaryPath)).catch(() => undefined),
|
|
1327
1397
|
])
|
|
1328
|
-
return { kind: 'windows', ...parseCommandCode({ credits, subscription, whoami }, now) }
|
|
1398
|
+
return { kind: 'windows', ...parseCommandCode({ credits, subscription, whoami, usageSummary }, now) }
|
|
1329
1399
|
},
|
|
1330
1400
|
},
|
|
1331
1401
|
deepseek: {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-tokenlens",
|
|
3
|
-
"version": "1.6.
|
|
3
|
+
"version": "1.6.7",
|
|
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",
|