npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

dsh-usage-display

v0.1.1

Published

多厂商余额/用量徽标(内置 DeepSeek 余额与智谱 GLM Coding Plan 配额):host 侧按轮次事件取数,经 SSE 同步到浏览器展示。

Readme

dsh-usage-display

npm version license dsh-plugin

在 dsh Web 界面显示模型厂商余额 / 套餐用量的会话头部徽标插件。host 进程从各家 厂商官方接口取数并缓存,浏览器侧只读本地路由渲染;API key 始终留在 host, 不会下发到浏览器。

内置三家厂商,按多厂商适配器架构组织,新增厂商只需实现一个 adapter:

| 厂商 | providerId | 展示内容 | | -------- | ------------ | -------------------------------------------------- | | DeepSeek | deepseek | 多币种账户余额(granted / topped-up 拆分) | | MiniMax | minimax | Token Plan 配额(5 小时窗口与周窗口) | | 智谱 GLM | zhipu | Coding Plan 配额(5h、周限额、工具用量三个百分比) |

效果预览

设置页(Settings → Plugins → “用量与余额”)可按通用显示 / DeepSeek / MiniMax / 智谱 GLM 分区调整展示偏好与告警阈值,保存后立即生效:

设置页“用量与余额”

特性

  • 会话头部用量徽标:展示当前模型对应厂商的主指标,点击展开明细面板并支持手动刷新。
  • 可配置告警阈值:余额低于阈值、配额用量超过阈值时,徽标状态点与进度条按 warn(黄)/ critical(红)两级染色。
  • 可配置进度可视化:percent 类指标在徽标与面板中支持文本、环形图、条形图三种 形态(display.panelStyle),徽标可用 auto 按指标类型自动选择。
  • 设置页热更新:Settings → Plugins → “用量与余额”页可即时调整展示偏好与告警 阈值,保存后 host 重建运行时并重新取数,无需重启;接入类字段仍走 cordis 配置。
  • 真正产生模型调用后自动取数:turn/start 与 turn/end 各全量刷新一次,切换模型时 只定向刷新新选中的厂商。
  • host 刷新落定后通过 SSE 通知浏览器重读本地缓存;浏览器绝不直连厂商 API。
  • 每家厂商独立缓存与故障隔离:一家失败不影响其他家,失败时保留上次成功值并标注更新时间。
  • 凭证只以引用名出现在配置中,每次取数由 dsh 凭证服务实时解析,轮换后下次请求即生效。

前置要求

  • Node.js(与运行中的 dsh 相同的版本即可)
  • pnpm
  • dsh CLI ≥ 0.1.0-rc.6

安装

从源码安装(开发)

# 1. 安装依赖并构建(产出 lib/index.js 与 lib/client.js)
pnpm install
pnpm run build

# 2. 安装进 web profile(在插件目录内执行 `add .` 等价;-w 按 workspace 链接)
dsh plugin --profile web add -w D:/Code/dsh-usage-display

# 3. 验证组合层,然后启动
dsh web --dump-config
dsh web

Windows 下路径务必用正斜杠,反斜杠会被解析成非法包名(如 Codedsh-usage-display)。 -w 需要保留:profile 自带 pnpm-workspace.yaml。

卸载:dsh plugin --profile web remove dsh-usage-display。

分发形式

  • npm:pnpm add dsh-usage-display(或 npm i dsh-usage-display)后执行 dsh plugin --profile web add dsh-usage-display;prepare 脚本会在安装时构建。
  • tarball:pnpm pack 后执行 dsh plugin --profile web add ./dsh-usage-display-<version>.tgz, 分发的是预构建产物,用户侧无需构建授权。
  • Git 安装:dsh plugin --profile web add github:deluo/dsh-usage-display。源码包由 prepare 脚本构建;pnpm ≥ 10 默认拒绝,需按提示在该 profile 的 pnpm-workspace.yaml 中给 allowBuilds 授权后重试。

配置

默认配置见 cordis.patch.yml,用户可在 profile 或 home 级的 cordis.patch.yml 中覆盖(后应用层整行替换):

dsh-usage-display:
  display:
    badgeStyle: 'auto' # auto | text | ring | bar;徽标上的进度形态
    panelStyle: 'ring' # text | ring | bar;面板里 percent 指标的形态
    showResetCountdown: true # 徽标配额文案是否带“距重置”倒计时
  providers:
    deepseek:
      enabled: true # 关闭后显示“已停用”,不再取数
      routeIds: ['deepseek-official'] # dsh provider 路由 id → 本插件 providerId(providerId 自动补入)
      apiKeyEnv: 'DEEPSEEK_API_KEY' # 凭证引用名,不是 key
      baseURL: 'https://api.deepseek.com'
      badgeCurrency: 'CNY' # 徽标主币种;账户无此币种时保持接口返回顺序
      warnBelow: 10 # 余额低于此值 → warn;'off' 关闭
      criticalBelow: 5 # 余额低于此值 → critical;'off' 关闭
    minimax:
      enabled: true
      routeIds: ['minimax', 'minimax-cn', 'minimaxi', 'minimax-coding-plan', 'minimax-token-plan']
      apiKeyEnv: 'MINIMAX_API_KEY' # 只存引用名,key 由 host 运行时解析
      apiKeyAliases:
        [
          'MINIMAX_TOKEN_PLAN_API_KEY',
          'MINIMAX_CODING_PLAN_API_KEY',
          'MINIMAX_CODING_API_KEY',
          'MINIMAX_CN_API_KEY',
          'MINIMAX_API_KEY',
          'MINIMAX_API_TOKEN',
        ]
      baseURL: 'https://api.minimaxi.com' # 含 minimaxi.com 走国内站,否则走 api.minimax.io
      badgeMetric: '5h' # 徽标主指标:5h | weekly
      resetTimeStyle: 'countdown' # 重置时间:countdown 倒计时 | time 本地时间点
      warnAbovePercent: 80 # 用量超过此百分比 → warn;'off' 关闭
      criticalAbovePercent: 90 # 用量超过此百分比 → critical;'off' 关闭
    zhipu:
      enabled: true
      routeIds: ['zai-coding-cn', 'zai-coding', 'zai', 'glm', 'zhipu', 'bigmodel', 'zhipuai']
      apiKeyEnv: 'ZHIPU_API_KEY'
      apiKeyAliases:
        [
          'ZAI_CODING_CN_API_KEY',
          'ZAI_CODING_API_KEY',
          'GLM_API_KEY',
          'ZAI_API_KEY',
          'BIGMODEL_API_KEY',
        ]
      baseURL: 'https://open.bigmodel.cn'
      authStyle: 'raw' # 'raw' | 'bearer'
      badgeMetric: '5h' # 徽标主指标:5h | weekly | tools
      resetTimeStyle: 'countdown' # 重置时间:countdown 倒计时 | time 本地时间点
      warnAbovePercent: 80 # 用量超过此百分比 → warn;'off' 关闭
      criticalAbovePercent: 90 # 用量超过此百分比 → critical;'off' 关闭

公共字段:

| 字段 | 类型 | 默认 | 说明 | | ---------- | ---------- | ------ | --------------------------------------------------------------------------------------------- | | enabled | boolean | true | 关闭后徽标显示“用量已停用”,不再取数 | | routeIds | string[] | [] | dsh provider 路由 id → 本插件 providerId,用于模型切换联动;providerId 本身总会自动加入映射 |

展示偏好(插件级 display):

| 字段 | 类型 | 默认 | 说明 | | -------------------- | ------------------------------------- | -------- | ---------------------------------------------------------------- | | badgeStyle | 'auto' \| 'text' \| 'ring' \| 'bar' | 'auto' | 徽标进度形态;auto 对 percent 指标用迷你条形图、金额保持纯文本 | | panelStyle | 'text' \| 'ring' \| 'bar' | 'ring' | 面板中 percent 指标的形态 | | showResetCountdown | boolean | true | 徽标配额文案是否带“距重置”倒计时 |

DeepSeek 专属:

| 字段 | 类型 | 默认 | 说明 | | --------------- | ----------------- | -------------------------- | -------------------------------------------------------------------------------------------- | | routeIds | string[] | ['deepseek-official'] | DeepSeek 官方 harness 适配器上报的 provider 路由 id;deepseek 作为 providerId 仍会自动加入 | | apiKeyEnv | string | DEEPSEEK_API_KEY | 凭证引用名,请求 GET {baseURL}/user/balance 时使用 | | baseURL | string | https://api.deepseek.com | 余额接口前缀 | | badgeCurrency | string | CNY | 徽标主币种(按接口返回的 currency 匹配,大小写不敏感);无此币种时保持接口顺序 | | warnBelow | number \| 'off' | 10 | 余额低于此值徽标变黄 | | criticalBelow | number \| 'off' | 5 | 余额低于此值徽标变红 |

智谱专属:

| 字段 | 类型 | 默认 | 说明 | | ---------------------- | ----------------------------- | -------------------------- | ----------------------------------------------------------------------------------------------------------------- | | apiKeyEnv | string | ZHIPU_API_KEY | 首选凭证引用名 | | apiKeyAliases | string[] | 见上 | 首选未配置时按顺序回退;指向模型适配器已在用的引用名即可直接复用其 key | | baseURL | string | https://open.bigmodel.cn | 实际请求 host 按域名路由:含 bigmodel.cn → open.bigmodel.cn,否则 api.z.ai | | authStyle | 'raw' \| 'bearer' | 'raw' | 首选鉴权头风格;401/403 自动换另一种重试,非法值在配置层直接报错 | | badgeMetric | '5h' \| 'weekly' \| 'tools' | '5h' | 徽标主指标 | | resetTimeStyle | 'countdown' \| 'time' | 'countdown' | 重置时间展示:countdown 显示紧凑倒计时(如 2h13m、2d3h);time 显示本地时间点(如 15:30、明天 08:30) | | warnAbovePercent | number \| 'off' | 80 | 用量超过此百分比徽标变黄 | | criticalAbovePercent | number \| 'off' | 90 | 用量超过此百分比徽标变红 |

MiniMax Token Plan 专属:

| 字段 | 类型 | 默认 | 说明 | | ---------------------- | ----------------------- | ------------------------------------------------------------------------------------ | --------------------------------------------------------------------- | | routeIds | string[] | ['minimax', 'minimax-cn', 'minimaxi', 'minimax-coding-plan', 'minimax-token-plan'] | dsh provider 路由 id → 本插件 providerId | | apiKeyEnv | string | MINIMAX_API_KEY | 首选凭证引用名 | | apiKeyAliases | string[] | 多个 Token Plan / Coding Plan / CN 别名 | 首选未配置时按顺序回退 | | baseURL | string | https://api.minimaxi.com | 区域识别基准地址;含 minimaxi.com 走国内站,否则走 api.minimax.io | | badgeMetric | '5h' \| 'weekly' | '5h' | 徽标主指标 | | resetTimeStyle | 'countdown' \| 'time' | 'countdown' | 重置时间展示形态 | | warnAbovePercent | number \| 'off' | 80 | 用量超过此百分比徽标变黄 | | criticalAbovePercent | number \| 'off' | 90 | 用量超过此百分比徽标变红 |

warn* / critical* 配反(如 warnBelow 小于 criticalBelow)时按更严格的方向归一; 全部设为 'off' 关闭该厂商的告警染色。

配置里从不出现 key 本身。apiKeyEnv / apiKeyAliases 都是凭证引用名,host 每次取数时 经 ctx.credentials.resolve() 解析:进程环境优先,其次 $DSH_HOME/.credentials.yaml (Models 页 / dsh credentials set 写入),再以项目与用户的 .env 回退。模型侧已配置的 智谱 key 可以直接复用——把 apiKeyEnv 指向模型适配器所用的引用名(dsh web --dump-config 可查到);托管存储里的 key 变更下次取数即生效,进程 env 的快照在启动时冻结。

使用

  • 打开会话后,头部操作区出现用量徽标:DeepSeek 显示余额金额,MiniMax 与智谱显示 配额窗口的已用百分比与重置时间;命中告警阈值时状态点与进度条变黄/红。
  • 徽标左侧的状态点只在纯文本/金额模式与异常状态时出现;有迷你条形图或环形图时 颜色信息已由图形表达,状态点自动隐藏。
  • 点击徽标展开当前模型对应厂商的明细面板,含状态、指标明细(金额行 / 配额表)、 更新时间与“刷新”按钮;配额指标按 display.panelStyle 渲染为环形图、条形图或 纯数字表格。手动刷新会等待真实取数落定。
  • MiniMax 与 GLM 配额重置时间都支持两种形态:countdown 显示 2h13m / 2d3h 等 倒计时,time 显示 15:30、明天 08:30、周三 08:30 等本地时间点。
  • 在 Settings → Plugins → “用量与余额”页按“通用显示 / DeepSeek / MiniMax / 智谱 GLM”分区, 保存后立即生效。该页写入的是用户设置文档;enabled / routeIds / apiKeyEnv / baseURL / authStyle 等接入类字段不在此暴露,仍在 cordis.patch.yml 中维护。
  • 切换模型时徽标高亮立即跟随(读模型选择目录 store);取数仍由轮次事件驱动, 切换后尚未发消息时展示的是缓存快照。
  • 当前模型的厂商未接入(routeIds 未覆盖)时徽标进入中性态显示“其他厂商”,面板列出 全部已接入厂商。
  • 每家厂商有五态:loading / ok / unconfigured / disabled / error;失败时展示 上次成功值并标注原更新时间。

本地 HTTP 接口

调试与二次集成用:

GET /plugins/dsh-usage-display/balance[?refresh=1]   # 聚合快照;refresh=1 强制真实取数
GET /plugins/dsh-usage-display/events                # SSE:balance-updated 事件 + 15s 心跳

/balance 只接受 GET,其余方法返回 405。响应示例:

{
  "providers": [
    {
      "providerId": "deepseek",
      "displayName": "DeepSeek",
      "kind": "balance",
      "status": "ok",
      "isAvailable": true,
      "metrics": [
        {
          "key": "cny",
          "label": "CNY 余额",
          "kind": "amount",
          "remaining": 110.0,
          "unit": "CNY",
          "detail": { "granted": "10.00", "toppedUp": "100.00" },
          "severity": "ok"
        }
      ],
      "fetchedAt": "2026-08-18T10:00:00.000Z",
      "cached": false,
      "severity": "ok"
    },
    {
      "providerId": "minimax",
      "displayName": "MiniMax Token Plan",
      "kind": "quota",
      "status": "ok",
      "isAvailable": true,
      "plan": "Max",
      "metrics": [
        {
          "key": "5h",
          "label": "5h限额",
          "kind": "percent",
          "used": 28,
          "resetsAt": "2026-08-18T13:00:00.000Z"
        },
        { "key": "weekly", "label": "周限额", "kind": "percent", "used": 45 }
      ],
      "fetchedAt": "2026-08-18T10:00:00.000Z",
      "cached": false
    },
    {
      "providerId": "zhipu",
      "displayName": "智谱 GLM",
      "kind": "quota",
      "status": "ok",
      "isAvailable": true,
      "plan": "pro",
      "metrics": [
        {
          "key": "5h",
          "label": "5h限额",
          "kind": "percent",
          "used": 28,
          "resetsAt": "2026-08-18T13:00:00.000Z"
        },
        { "key": "weekly", "label": "周限额", "kind": "percent", "used": 12 },
        { "key": "tools", "label": "工具用量", "kind": "percent", "used": 8 }
      ],
      "fetchedAt": "2026-08-18T10:00:00.000Z",
      "cached": false
    }
  ],
  "activeBySession": { "<会话id>": { "providerId": "zhipu", "model": "glm-4.7" } },
  "routes": {
    "deepseek-official": "deepseek",
    "deepseek": "deepseek",
    "minimax": "minimax",
    "minimax-cn": "minimax",
    "zai": "zhipu",
    "glm": "zhipu"
  },
  "display": { "badgeStyle": "auto", "panelStyle": "ring", "showResetCountdown": true },
  "providerDisplay": {
    "minimax": { "resetTimeStyle": "countdown" },
    "zhipu": { "resetTimeStyle": "countdown" }
  }
}

普通读只返回本地缓存(cached: true),不会触发厂商 API;?refresh=1 等待取数并返回 新鲜快照(cached: false)。

项目结构

dsh-usage-display/
├── package.json          # 双面插件声明(dsh.bundle + dsh.client)
├── cordis.patch.yml      # host loader 行与默认配置
├── tsconfig.json         # 类型检查配置
├── tsdown.config.ts      # host / client 双 bundle 构建
├── scripts/
│   ├── smoke-client.mjs  # 客户端 bundle 冒烟测试
│   └── smoke-host.mjs    # host 编排冒烟测试
└── src/
    ├── index.ts          # host 入口:HTTP 路由 + SSE + 会话事件编排
    ├── types.ts          # 两侧共用的快照 / 指标契约
    ├── settings.ts       # 设置页可调子集目录(各厂商 tunable 类型聚合)
    ├── core/
    │   ├── registry.ts       # 厂商注册表:schema / tunable 抽取合并 / 展示偏好聚合
    │   └── usage-service.ts  # 缓存 / in-flight 去重 / 故障隔离
    ├── providers/
    │   ├── types.ts          # ProviderAdapter SPI
    │   ├── deepseek.ts       # DeepSeek 余额适配器
    │   ├── minimax.ts        # MiniMax Token Plan 配额适配器
    │   └── zhipu.ts          # 智谱 GLM 配额适配器
    └── client/
        ├── index.ts      # 浏览器入口:读取快照 + 注册徽标
        ├── routes.ts     # 本地路由常量(与 host 侧对齐)
        ├── usage-store.ts
        ├── UsageBadge.tsx
        └── SettingsTab.tsx # 设置页(Plugins 分区 tab)

接入新厂商

  1. 在 src/providers/<id>.ts 实现 ProviderModule,fetch() 负责取数并把 wire 格式 归一化为 ProviderSnapshot(异常在内部吞掉并返回 error 快照,正常路径不 throw); 指标 kind 支持 amount / window / percent。如需设置页热更新,模块里声明 tunable(schema + extract + merge)与可选的 display 偏好,字段默认值只在模块内 维护一份。
  2. 在 src/index.ts 的 createRegistry([deepseek, minimax, zhipu]) 中登记模块,并在 SETTINGS_SCHEMA 里补一行该厂商的 tunable.schema。
  3. 在 src/settings.ts 补该厂商的可调类型,客户端 SettingsTab.tsx 按需要增加分区。
  4. 在 cordis.patch.yml 补该厂商的默认配置(只写需要覆盖的字段,其余交给 schema 默认值)。
  5. pnpm run build 后按开发流程验证。

最小骨架:

// src/providers/acme.ts
// (z 来自 @deepseek-ai/schemastery;withCommonConfig / ProviderModule / ProviderAdapter
//   来自 providers/types.ts,此处省略 import 语句)
export const acme: ProviderModule<AcmeConfig, AcmeTunable, 'acme'> = {
  id: 'acme',
  displayName: 'Acme',
  kind: 'balance', // 或 'quota'
  config: withCommonConfig({
    apiKeyEnv: z.string().default('ACME_API_KEY'),
    baseURL: z.string().default('https://api.acme.example'),
    // 如需设置页热更新:把可调字段与 tunable schema 共用一份定义
  }),
  // tunable / display 可选,缺省即没有设置页热更新与专属展示偏好
  create: (ctx, config) => new AcmeAdapter(ctx, config),
}

class AcmeAdapter implements ProviderAdapter {
  readonly id = 'acme'
  readonly displayName = 'Acme'
  readonly kind = 'balance' as const
  async fetch(): Promise<ProviderSnapshot> {
    // 取数 + 归一化;错误时返回 status: 'error' 的快照
  }
}

开发

pnpm install
pnpm run build       # 产出 lib/index.js(host ESM)与 lib/client.js(浏览器 loader 闭包)
pnpm run typecheck   # tsc --noEmit(基于 npm 发布的 @deepseek-ai 类型)
pnpm run format      # prettier 统一格式化(提交前执行;format:check 仅检查)
pnpm run smoke       # 客户端 bundle 冒烟:mock 模块加载器 + mock ctx,无需浏览器
pnpm run smoke:host  # host 冒烟:多厂商编排、模型切换联动、鉴权重试,无需 key

迭代循环:改 host 半 → pnpm run build → 重启 dsh web;改 client 半 → pnpm run build → 刷新页面。本地 node_modules 里的 @deepseek-ai/* 来自 npm 发布版本,若运行中的 dsh 版本接口有变化,请同步 peerDependencies 后重新 pnpm install。

已知限制

  • 余额为异步结算,徽标展示的是近实时快照,面板标注原更新时间。
  • 本地路由与 SSE 端点不带鉴权(dsh webServer 的设计如此);dsh web 默认绑定 127.0.0.1,若绑定 0.0.0.0 会把这些只读端点暴露到网络。
  • turn/end 对空轮次(输入被拒等)也会发出,多一次无害的余额查询。
  • 模型切换没有“点击即触发”的持久事件:高亮点击即生效,数据在下一轮次消息时才刷新。

参考

License

MIT