Skip to content
dsh.fish
Bundle

@gongshiyun/dsh-usage-dashboard

DeepSeek 余额与用量统计插件:余额、当前会话/最近一次消耗、各模型剩余对话次数

Source
gongshiyun
stars
1 stars
License
MIT
Updated
Updated 5 days ago

Readme

# dsh-usage-dashboard

[English](README.en.md) | 中文

DeepSeek Harness(DSH)插件:展示 **DeepSeek 账户余额**、**当前会话预估消耗**、**历史对话明细(每个对话的 token 与金额)**,并根据历史会话的平均消耗,估算**各模型剩余对话次数**。

## 功能

- **余额**:调用 DeepSeek 官方 `GET /user/balance` 接口,展示总余额 / 充值余额 / 赠送余额(CNY 或 USD)。
- **当前会话预估消耗 + 还能几轮**:在输入框下方、官方 token 统计行之后另起一行,实时显示「本次会话预估金额 · 余额 · 预估还能几轮」(剩余轮数 = ⌊余额 ÷ 当前会话每轮平均消耗⌋)。
- **对话明细(全局看板)**:列出每个历史对话的创建时间、输入 token、输出 token 与折算金额(按创建时间倒序,自动跳过空会话;「当前」会话会标注)。
- **各模型剩余对话次数**:按模型聚合历史会话,`剩余次数 = ⌊余额 ÷ 单次会话平均消耗⌋`,同时展示会话数、平均消耗、累计消耗与 token 明细。

## 展示位置

- **输入框下方一行**(`conversation.composer.dock`,order 200):当前会话预估消耗、当前余额、预估还能对话几轮,随对话每 4 秒自动刷新。
- **「设置 → 用量与余额」全局看板**(`settings.section`):余额卡片 + 对话明细表 + 各模型剩余对话次数。

## 安装

插件必须能被 Cordis Loader 从 **profile 目录**按名称解析。DSH 桌面版(Electron)与 Web 版共用同一套插件体系,只是使用不同的 profile(`desktop`/`web`),安装步骤相同,仅把下面的 `desktop` 换成实际使用的 profile 名(例如 Web 版用 `web`)。默认 Windows 路径:

- 主目录(`$DSH_HOME`):`C:\Users\<you>\.dsh`
- 桌面版 profile 目录:`C:\Users\<you>\.dsh\profiles\desktop\`
- Web 版 profile 目录:`C:\Users\<you>\.dsh\profiles\web\`
- 插件解析来源:`$DSH_HOME\profiles\<profile>\node_modules`(pnpm 管理)+ 扁平回退 `$DSH_HOME\profiles\node_modules`

下面以 desktop 为例;**Web 版把 `desktop` 换成 `web` 即可**。

### 方式一(推荐):`dsh plugin add` 一键安装

本包声明了 `dsh.bundle.patch`(即 `cordis.patch.yml`),`dsh plugin add` 会 `pnpm add`
并把它自动追加进 profile 的 `dsh.profile.bundles`,从而完成「安装 + 组合」两步:

```bash
dsh plugin --profile desktop add @gongshiyun/dsh-usage-dashboard
```

然后重启/刷新 DSH Desktop(Web 版刷新页面)。可用 `dsh --profile desktop --dump-config` 确认 `usage-dashboard` 条目已生效。

> 注意:npm 上**不带 scope** 的 `dsh-usage-dashboard` 是另一个同名但无关的插件,装它不会得到本项目。请始终使用带 `@gongshiyun/` 前缀的完整包名。

### 方式二:手动安装(非 bundle 包或离线环境)

1. 把本包安装进 profile 的 node_modules:

   ```bash
   cd "$DSH_HOME/profiles/desktop"
   pnpm add <本包路径或包名>
   ```

2. 编辑 `$DSH_HOME\profiles\desktop\cordis.patch.yml`,在顶层插入一行(**不要**编辑 desktop 根目录的 `cordis.yml`,它每次启动都会被重写为 `[]`):

   ```yaml
   - insert:
       - id: usage-dashboard
         name: '@gongshiyun/dsh-usage-dashboard'
         config:
           currency: CNY
           pricing:
             - effective: 2026-07-24T00:00:00Z
               models:
                 - model: deepseek-v4-flash
                   inputPerM: 1
                   cacheReadPerM: 0.02
                   outputPerM: 2
                 - model: deepseek-v4-pro
                   inputPerM: 3
                   cacheReadPerM: 0.025
                   outputPerM: 6
             - effective: 2026-08-16T16:00:00Z
               models:
                 - model: deepseek-v4-flash
                   inputPerM: 1.5
                   cacheReadPerM: 0.05
                   outputPerM: 4.5
                   peak:
                     inputPerM: 3
                     cacheReadPerM: 0.1
                     outputPerM: 9
                   offPeak:
                     inputPerM: 1.5
                     cacheReadPerM: 0.05
                     outputPerM: 4.5
                 - model: deepseek-v4-pro
                   inputPerM: 4.5
                   cacheReadPerM: 0.15
                   outputPerM: 13.5
                   peak:
                     inputPerM: 9
                     cacheReadPerM: 0.3
                     outputPerM: 27
                   offPeak:
                     inputPerM: 4.5
                     cacheReadPerM: 0.15
                     outputPerM: 13.5
   ```

3. 重启 DSH Desktop。

## 配置

| 键 | 类型 | 默认 | 说明 |
|---|---|---|---|
| `apiKeyEnv` | credential-ref | `DEEPSEEK_API_KEY` | API Key 凭证引用名 |
| `baseURL` | string | `https://api.deepseek.com` | DeepSeek API 根地址 |
| `currency` | `CNY` \| `USD` | `CNY` | 计价与余额展示货币(**必须与 `pricing` 单位一致**) |
| `balanceCacheMs` | number | `60000` | 余额缓存时长(毫秒) |
| `pricing` | array | 见下 | **价目历史**(era 列表),每个 era 有生效时刻与各模型单价 |

`pricing` 为**价目历史**(按生效时间排序,成本按每个模型调用的事件发生时刻取当时生效的价目计算):

```yaml
pricing:
  - effective: 2026-07-24T00:00:00Z   # era 生效时刻(ISO 8601 UTC)
    models:
      - model: deepseek-v4-flash
        inputPerM: 1          # 平段价:输入(缓存未命中)
        cacheReadPerM: 0.02   # 平段价:输入(缓存命中)
        outputPerM: 2         # 平段价:输出
  - effective: 2026-08-16T16:00:00Z   # 官方 8.17 峰谷定价(北京 8/17 生效)
    models:
      - model: deepseek-v4-flash
        inputPerM: 1.5
        cacheReadPerM: 0.05
        outputPerM: 4.5
        peak:                 # 高峰时段单价(与 offPeak 同时存在才生效)
          inputPerM: 3
          cacheReadPerM: 0.1
          outputPerM: 9
        offPeak:              # 谷段单价
          inputPerM: 1.5
          cacheReadPerM: 0.05
          outputPerM: 4.5
```

- 事件时刻早于首个 era 时按首个 era 计价;未配置的模型回退到该 era 内 `model: "*"` 条目(若有),否则按 0 计。
- **官方再调价时,往列表里追加一个 `effective` 更新的 era 即可**——旧会话自动按历史价核算,新会话按新价核算。
- 兼容旧格式:直接给出平铺的模型条目(无 `effective`/`models`)会被当作单个 era 处理。

### 默定价目历史(人民币 / 1M token)

| 生效时间 | 模型 | 时段 | 输入(未命中) | 输入(命中) | 输出 |
|---|---|---|---|---|---|
| 2026-07-24(V4 上线) | `deepseek-v4-flash` | 平段 | ¥1 | ¥0.02 | ¥2 |
| 2026-07-24 | `deepseek-v4-pro` | 平段 | ¥3 | ¥0.025 | ¥6 |
| 2026-08-16T16:00Z(北京 8/17 起) | `deepseek-v4-flash` | 高峰 | ¥3 | ¥0.10 | ¥9 |
| 2026-08-16T16:00Z | `deepseek-v4-flash` | 谷段 | ¥1.5 | ¥0.05 | ¥4.5 |
| 2026-08-16T16:00Z | `deepseek-v4-pro` | 高峰 | ¥9 | ¥0.30 | ¥27 |
| 2026-08-16T16:00Z | `deepseek-v4-pro` | 谷段 | ¥4.5 | ¥0.15 | ¥13.5 |

高峰时段:UTC 01:00–04:00 与 06:00–10:00(北京时间 09:00–12:00 与 14:00–18:00);其余为谷段(价格为高峰一半)。

来源:<https://api-docs.deepseek.com/zh-cn/quick_start/pricing/>(英文:<https://api-docs.deepseek.com/quick_start/pricing/>)。注意:**默认价是内置的、不会自动跟随官方后续调价**——官方再次调整价格后,需追加一个新 era(或等插件发布新默认值),插件本身不会自动抓取官方页面。

## 数据口径与假设

- **token 口径**:直接读取会话日志 `assistant/message` 事件的 provider `usage` 字段
  (`inputTokens` = 缓存未命中输入、`cacheReadTokens` = 缓存命中输入、`outputTokens` = 输出,
  与 DeepSeek 的 `prompt_cache_miss_tokens` / `prompt_cache_hit_tokens` / `completion_tokens` 一一对应)。
- **重试去重**:同一 `(turn, step)` 的多次 `assistant/message`(`llm/retry` 重试)只保留最后一次,
  与 token-meter 的口径一致。
- **成本公式**:`cost = (inputTokens×inputPerM + cacheReadTokens×cacheReadPerM + outputTokens×outputPerM) / 1e6`。
- **历史会话来源**:优先走 `ctx.sessionQuery`(合并内存中的 live 会话与持久化的冷会话);
  无该服务时退化为仅统计当前已加载进内存的会话。持久化会话的用量按会话 id 一次性缓存,
  重启后自动重建。
- **「对话明细 / 最近一次」**:`conversations` 按会话创建时间倒序,仅包含有实际 token 消耗的会话(自动跳过空会话);其中除当前会话外的第一条即「最近一次对话」。
- **「剩余对话次数(模型)」**:`⌊余额 ÷ 该模型单次会话平均消耗⌋`;该模型无历史或平均消耗为 0 时显示 `—`。
- **「预估还能几轮」**:`⌊余额 ÷(当前会话累计消耗 ÷ 当前会话轮数)⌋`;当前会话尚无输出轮次时显示 `—`。
- **余额金额字段为字符串**:DeepSeek 返回的 `total_balance` 等为字符串,本插件在展示与计算时转成数字。

## 架构说明(供二次开发)

- **host**(`lib/index.js`):Cordis 插件 `{ name, inject, apply, Config }`。核心是一个
  `TypertRemoteService` 子类 `UsageDashboardGateway`,暴露 `balance()` 与 `overview(sessionId?)`
  两个 SRC Remote 端点。SRC(source)模式由 `dsh-api-gateway` 的 `TypertGatewayService` 在运行时
  从 `@Remote` 标记推导参数与端点,**无需 Typert 编译器生成的 strict 描述符**——因此本插件用
  `installRemote()` 手动展开装饰器(plain-JS 环境无装饰器语法)。
- **client**(`lib/client.js`):`window.__ModuleLoader__.load({ id, factory })` 形态,
  通过 `ctx.slots.inject(...)` 在 `settings.section` 与 `sidebar.footer.action` 两个槽位注册
  React 组件;数据经 `ctx.connection.rpc.call('/api', 'usageDashboard/<method>', { args })` 获取。

## 限制

- 余额接口为按需轮询(侧边栏胶囊 60s、仪表盘 4s),非实时推送。
- 无网络或未配置 API Key 时,余额显示错误提示,成本统计仍可用(取决于本地会话数据)。
- 跨会话的历史平均依赖 `dsh-session-query` 服务(DSH 默认组合已包含)。

Install

dsh plugin --profile web add github:gongshiyun/dsh-usage-dashboard

Profile: web

  • This source has no pinned commit, so a later push upstream changes what installs. Prefer pinning a commit.
Source