Hacktoberfest 2026:維護者為十月標記出來的 issue,仍然開放、適合新手。 瀏覽 Hacktoberfest issue

[bug] usage token-plan 对按月计量的 Token Plan 账号返回空:API 返回 per1MonthPercentage,CLI 只读 per5Hour* / per1Week*

未關閉
#231 1 則留言 0 個 reaction 已指派 0 人 在 GitHub 檢視

維護者通常 1 天內回覆

還沒有人認領這個 Issue。

評估

難度
3/5
預估耗時
1-2 天
新手友好度
68/100
Issue 類型
缺陷
描述清晰度
基本清楚
活躍度
活躍
技術堆疊
typescript
領域
cli

研究方向

Start in packages/commands/src/commands/usage/token-plan.ts by tracing readUsage() from the API response into the usage view, then inspect quota-box.ts for the missing-data behavior. Reproduce the issue with the provided console call and a monthly Token Plan account. Done means monthly usage is represented in the CLI and JSON output, while genuinely missing usage remains distinguishable from unlimited usage.

由索引模型根據 Issue 內容生成。

描述

环境

bl --version 2.0.1
OS Windows 11
Node.js v24.12.0
站点 国内站(console_site: domestic, console_region: cn-beijing)
套餐 Token Plan 个人版
登录方式 bl auth login --console(登录态有效)

现象

bl usage token-plan 两个窗口都显示为「可能不限量」,--output json 返回空对象:

$ bl usage token-plan
┌────────────────────────────────────────────────────────────────────────────┐
│ Token Plan Usage                                                           │
│ Generated at: 2026-09-26 13:14:40 (local time)                             │
├────────────────────────────────────────────────────────────────────────────┤
│ 5-hour quota                                                               │
│ The 5-hour limit may be unlimited; verify in the Bailian Token Plan console.│
├────────────────────────────────────────────────────────────────────────────┤
│ 1-week quota                                                               │
│ The 1-week limit may be unlimited; verify in the Bailian Token Plan console.│
└────────────────────────────────────────────────────────────────────────────┘

$ bl usage token-plan --output json --quiet
{}

但该账号是有用量的,且控制台能正常显示。 所以这不是「不限量」,而是 CLI 没有读到数据。

根因:API 返回月计量字段,CLI 只声明了 5 小时 / 周字段

直接调用同一条底层 API(bl usage token-plan 内部使用的那个),可以看到返回了真实的用量数据:

$ bl console call --api "zeldaHttp.apikeyMgr./tokenplan/personal/api/v2/usage" --data '{}' --output json
{
  "code": "200",
  "data": {
    "DataV2": {
      "ret": ["SUCCESS::接口调用成功"],
      "data": {
        "msg": "Success.",
        "code": "SUCCESS",
        "data": {
          "per1MonthPercentage": 0.004482845333333333,
          "per1MonthResetTime": 1790784000000
        },
        "requestId": "9dc4ca84-5a41-9f08-b9ae-39832766292f",
        "success": true
      }
    },
    "success": true,
    "httpStatus": 200,
    "errorCode": "",
    "api": "zeldaHttp.apikeyMgr./tokenplan/personal/api/v2/usage",
    "errorMsg": ""
  },
  "httpStatusCode": "200",
  "requestId": "9dc4ca84-5a41-4f08-b9ae-39832766292f",
  "successResponse": true
}

即该账号是按自然月计量的(per1MonthPercentage),当前用量约 0.45%。

而 packages/commands/src/commands/usage/token-plan.ts 只声明并读取 5 小时 / 周两类字段:

interface TokenPlanUsage {
  per5HourPercentage?: number;
  per5HourResetTime?: number;
  per1WeekPercentage?: number;
  per1WeekResetTime?: number;
}

function readUsage(result: unknown): TokenPlanUsage {
  const response = unwrapResponse(result as Record<string, unknown>);
  const usage: TokenPlanUsage = {};

  const per5HourPercentage = readNumber(response.per5HourPercentage);
  if (per5HourPercentage !== undefined) usage.per5HourPercentage = per5HourPercentage;
  const per5HourResetTime = readNumber(response.per5HourResetTime);
  if (per5HourResetTime !== undefined) usage.per5HourResetTime = per5HourResetTime;
  const per1WeekPercentage = readNumber(response.per1WeekPercentage);
  if (per1WeekPercentage !== undefined) usage.per1WeekPercentage = per1WeekPercentage;
  const per1WeekResetTime = readNumber(response.per1WeekResetTime);
  if (per1WeekResetTime !== undefined) usage.per1WeekResetTime = per1WeekResetTime;

  return usage;
}

per1Month* 不在读取范围内,因此四个字段全部为 undefined,readUsage() 返回 {},视图按「字段缺失 = 可能不限量」渲染。

字段对照

API 实际返回(本账号) CLI 读取 是否命中
per1MonthPercentage per5HourPercentage ❌
per1MonthResetTime per5HourResetTime ❌
— per1WeekPercentage ❌
— per1WeekResetTime ❌

对比 #135(该功能的最初请求)中贴出的响应,那种账号返回的是 per5HourPercentage / per1WeekPercentage:

"data": {
  "per5HourPercentage": 0.43565880333333334,
  "per1WeekPercentage": 0.130712521,
  "per5HourResetTime": 1785868560000,
  "per1WeekResetTime": 1786417680000
}

可见 Token Plan 至少存在两种计量形态(5 小时 + 周窗口 / 自然月),当前实现只覆盖了前者。

影响

  • bl usage token-plan 对按月计量的账号恒返回空,即使账号有用量、控制台可见。
  • --output json 返回 {},下游消费者无法区分「真的不限量」与「字段名不匹配」。这一点影响面较大:第三方工具(例如 DSH 插件 dsh-cost-meter 的「百炼 CLI」额度来源)拿到 {} 后会判定为异常数据并报错,用户看到的是「CLI 返回的额度格式无效」,进而被误导去升级 CLI——而 CLI 已是最新版。
  • quota-box.ts 中的注释 /** Usage ratio in [0, 1]; absent means no data (possibly unlimited). */ 以及文案里的 "may be unlimited" 表明作者已意识到该路径存在歧义,但当前无法区分。

建议

  1. 补充月计量字段支持:在 TokenPlanUsage 中增加 per1MonthPercentage / per1MonthResetTime,并在视图中作为第三个窗口渲染(或在 5 小时 / 周缺失时作为回退窗口)。
  2. 或改为按返回字段动态渲染:遍历响应中实际存在的 per*Percentage 字段,按前缀生成对应窗口标签(per5Hour → 5-hour、per1Week → 1-week、per1Month → 1-month),避免为每种新计量形态改一次代码。
  3. 区分「无数据」与「不限量」:当响应成功但无任何 per*Percentage 字段时,JSON 输出建议给出可判别的信号(例如 {"unlimited": true} 或显式 null),而不是裸 {},以便下游区分。
  4. 文档中补充说明 Token Plan 存在多种计量形态。

复现步骤

  1. 使用按月计量的 Token Plan 个人版账号,bl auth login --console 完成登录。
  2. 运行 bl usage token-plan(或加 --output json --quiet)。
  3. 观察两个窗口均显示 "may be unlimited",JSON 为 {}。
  4. 运行 bl console call --api "zeldaHttp.apikeyMgr./tokenplan/personal/api/v2/usage" --data '{}',可见响应中含 per1MonthPercentage 等真实数据。

备注

  • 上述 console call 输出仅含百分比与时间戳,未包含任何凭据。
  • 该账号的 bl token-plan harness-quota 能正常返回 7 项 Harness 工具额度(status 均为 issued),说明订阅本身有效、控制台登录态正常,问题仅限于 usage token-plan 的字段映射。
主要語言
TypeScript
星號
536
分支
36
平均合併
21 小時 41 分鐘
30 天內合併 PR
35

環境準備

  • 沒有 Dockerfile 或 Docker Compose 檔案
  • 沒有 Pull Request 範本
  • 閱讀貢獻指南

從這裡開始

  1. 先讀完整個 Issue,再讀專案的貢獻指南。
  2. 在 Issue 下留言說明你要接手 —— 這能避免兩個人做同樣的事。
  3. Fork 儲存庫,在一個分支上完成修改。
  4. 送出 Pull Request,並在描述裡引用這個 Issue 編號。

modelstudioai/cli 的其他 Issue

查看 modelstudioai/cli 的全部 Issue

相似的 Issue

更多 TypeScript Issue

把新 issue 寄到你的電子郵件信箱

精選適合新手參與的 GitHub issue 摘要。