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 CHANGED
@@ -4,9 +4,23 @@
4
4
 
5
5
  **版本记录约定**:同一发布日只保留一个章节,标题取当日**最后一个**已发布版本号;当日多次发布的改动合并到该章节,并在标题下注明当日实际发布过的版本号(npm 上仍可安装这些独立版本)。若当日已有发布,后续小改动不再单独增加版本号,而是并入下一篇日志。这样日志按天规整、不出现同日多个小版本。
6
6
 
7
- ## 1.6.5 — 2026-11-05
7
+ ## 1.6.7 — 2026-11-05
8
8
 
9
- (当日已发布版本:v1.6.5。修复 GitHub issue #1)
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 = `(granted - remaining)/granted` (only when the API reports the grant) | `plan`, `credits` (USD), `account` |
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; Command Code monthly percentage is not guessed when no grant is reported.
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 352 tests.
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 未报告 grant 时不计算月度百分比。
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`:**352 个自动化用例**,覆盖 Host 数据层、供应商适配器(含小米 MiMo 控制台 Cookie 适配器)、统计折叠、各 harness 读取、Design Plan 周期账本与额度计价、窗口锚点切片、工作区自动识别、插件集成与浏览器端渲染 / 交互。
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.5'
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), `granted` is the
473
- * plan's monthly grant; the windows' `used`/`cap` are USD, `resetAt` is epoch
474
- * seconds or milliseconds.
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
- const limited = limits.limited === true || limits.exceeded === true
483
- const windowStatus = limited ? 'limited' : 'ok'
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: windowStatus,
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
- remaining !== null && granted !== null && granted > 0
513
- ? normalizePercent(((granted - remaining) / granted) * 100)
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
- status: monthlyPercent === null ? 'unknown' : windowStatus,
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: remaining !== null && granted !== null && granted > 0 ? Math.max(0, granted - remaining) : null,
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
- const [subscription, whoami] = await Promise.all([
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.5",
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",