Skip to content
dsh.fish
Bundle

@max/dsh-cost-meter

在对话框下方、上下文用量的右侧显示本次会话的 token 用量与按 DeepSeek 官方定价折算的人民币费用

Source
PennChong95
License
MIT
Updated
Updated 8 days ago

Readme

# @max/dsh-cost-meter

在 DeepSeek Harness Web 界面里,把**本次会话的 token 用量和人民币费用**显示在对话框下方、**上下文用量的右侧**。

零依赖、零构建:`client.js` 就是浏览器直接加载的产物,`index.js` 是空的 Host 半侧。

## 安装(给拿到这个包的人)

先拿到包含 `cordis.patch.yml` 的**整个包**(`.tgz` / git 仓库 / 本地目录都行),再让 DSH 把它装进当前 profile。

**方式一:压缩包或本地目录**

```
dsh plugin add "D:\下载\max-dsh-cost-meter-<版本>.tgz"
dsh plugin add "D:\下载\dsh-cost-meter"
```

**方式二:git**

仓库地址 <https://github.com/PennChong95/dsh-cost-meter>(已打上 GitHub topic **`dsh-plugin`**,社区插件市场大多按这个 topic 自动收录):

```
dsh plugin add "github:PennChong95/dsh-cost-meter"
```

- 仓库里必须包含**已构建的产物**:本包没有构建步骤,`client.js` 就是产物,直接提交即可。
- git 安装会拉取整棵仓库,`package.json` 的 `files` 白名单不生效——别把 `node_modules` 之类的东西提交上去。
- 国内使用者的可达性是个变量:DSH 安装前会用 `git ls-remote` 探一次 GitHub(默认 5 秒超时),不通时界面会提示「无法访问 GitHub」,而 npm 镜像只能替代 npm 源、替代不了 GitHub 下载。给国内用户分发时,`.tgz` 直发最稳。

**Desktop 应用用户**:desktop profile 由应用独占,命令行会被拒绝,请走界面 —— 侧边栏 **插件** → **添加插件**,把上面的 spec(`.tgz` 或目录的绝对路径、git 地址)粘进输入框 → **安装**。安装对话框里能看 pnpm 输出,装完默认启用。

装好后界面上应该出现一个 `¥` 胶囊,位于输入框下方、上下文用量环的右侧;点开是明细面板。

### 注意事项

- 本包在 **DSH `0.2.0-rc.2`**(Desktop 版)上验证通过。它依赖 `conversation.composer.dock` 插槽与 `tokenUsage`、`modelSelection` 两个会话投影;更早的 DSH 版本若没有这些,插件会加载失败(插件列表里能看到原因)。
- **安装后请刷新一次页面**:运行中的页面持有已求值的旧模块。
- 目前 DSH 的插件不支持自动更新:升级要**先卸载再装新版**。
- 本包没有 `dependencies`,也没有 `prepare` 脚本,因此安装时不会触发任何依赖构建;通过 git 安装也不会遇到 pnpm 的构建脚本拦截。
- **改名要改三处**:`package.json` 的 `name`、`client.js` 的 `id`(必须是同一个字符串,客户端模块靠它注册自己)、`cordis.patch.yml` 的 `name:`(YAML 里以 `@` 开头的值**必须加引号**)。顺带把 `client.js` 的 `NS`、`STYLE_ID`、`STORAGE_PREFIX` 也换掉,避免与同名插件撞命名空间。`dsh.bundle.patch`、`exports` 不用动。

## 它显示什么

- **胶囊按钮**:`¥0.1234` —— 本次会话按 DeepSeek 官方价目折算的花费。
- **点击后展开明细**(不会超出视口):
  - 输入·缓存命中 / 输入·缓存未命中 / 输入·缓存写入 / 输出 的 token 数与各自金额;
  - 总 tokens;
  - 高峰时段 / 空闲时段 分别累计的金额(`mode: ledger`);
  - 计价模型、当前时段、当前费率(元/百万 tokens)。

胶囊元素的 CSS `order` 为 `1`,而 composer dock 中上下文用量环排在插槽之后,因此本插件始终落在**上下文用量的右边**。

## 定价口径

价目取自 DeepSeek 官方「模型 & 价格」页(人民币 / 百万 tokens):

| 模型 | 输入·缓存命中 | 输入·缓存未命中 | 输入·缓存写入 | 输出 |
| --- | --- | --- | --- | --- |
| `deepseek-flash` 高峰 | 0.04 | 2 | 2 | 8 |
| `deepseek-flash` 空闲 | 0.02 | 1 | 1 | 4 |
| `deepseek-v4-pro` 高峰 | 0.30 | 9 | 9 | 27 |
| `deepseek-v4-pro` 空闲 | 0.15 | 4.5 | 4.5 | 13.5 |

**时段规则**(官方说明:*「北京时间周一至周五(不含中国法定节假日)9:00 - 12:00、14:00 - 18:00 为高峰时段;其余时段,包括周末及中国法定节假日全天均为空闲时段」*):

- 高峰 = 北京时间**周一至周五** ∧ **不是中国法定节假日** ∧ 落在 9:00–12:00 或 14:00–18:00。
- 其余全部空闲,价格为高峰的一半,具体包括:
  - 每个周六、周日;
  - **调休上班的周末**(例如 2026-01-04 周日、2026-02-14 周六、2026-05-09 周六、2026-09-20 周日、2026-10-10 周六)——按官方口径,周末即使被调休成工作日也按空闲计费,插件不做“调休补班按高峰”的处理;
  - **中国法定节假日全天**,即使落在周一至周五(例如 2026-10-01 周四、2026-02-17 周二、2026-06-19 周五)。

**节假日表**按国务院办公厅年度通知内置,当前含 **2026 年**(国办发明电〔2025〕7 号,2025-11-04:元旦 1/1–1/3,春节 2/15–2/23,清明 4/4–4/6,劳动节 5/1–5/5,端午 6/19–6/21,中秋 9/25–9/27,国庆 10/1–10/7,共 33 天)。表里没有的年份,面板会提示“该年节假日安排尚未内置”,此时可用 `extraHolidays` 临时补上;内置表写错时用 `extraWorkdays` 把某天改回工作日规则(该日期优先于节假日判断)。

其它:

- `cacheWrite` 按缓存未命中价计:DeepSeek 的 usage 把提示缓存写入计入普通输入,官方没有单独的缓存写入单价。
- 已下线的 `deepseek-v4-flash`、`deepseek-v4-flash-vision-exp` 按 Flash 价计费,`deepseek-v4-pro-0813` 按 Pro 价计费。
- 官方口径以「中国法定节假日」为准;插件内置的是国务院办公厅通知里的**全部放假日**(含调休连休日),这比严格意义的 11 天法定节假日更宽,与“全国都放假”的实际计费场景一致。若你只想按 11 天法定节假日算,用 `extraWorkdays` 把多出来的连休日改回工作日即可。

**这些数字是估算**:它由本会话持久化的 usage 折叠得出,不含子会话、其他会话,也不含任何非 token 计费项。实际扣费以 DeepSeek 开放平台账单为准。

## 已知限制

- **首次观察到的历史用量按当时费率一次性计入。** `tokenUsage` 只给会话总量、没有逐请求时间戳,所以插件首次挂载(安装后、刷新后第一次进入某会话)时,会把当时已有的全部用量按当下的时段费率计入。安装前跨过 09:00、18:00 或节假日边界的会话,首次数字可能偏高或偏低;此后每次增量都按发生时刻的费率计。
- **节假日表随插件版本走。** 国务院办公厅通常在每年 11 月发布次年的安排;内置表更新前,次年的节假日会被当成普通工作日(面板会提示)。跨年时请留意更新插件或临时补 `extraHolidays`。
- **作用域是当前会话。** 子代理会话、其他并行会话的用量不在其中。
- **账本存在浏览器 localStorage**(键 `max-dsh-cost-meter:v2:<sessionId>`)。键里的版本随计价规则变更递增:规则变化后不会与旧账本混算,而是按新的规则重新对现存总量计价。清理浏览器数据会把累计金额清零(随后从当前总量重新起算)。
- 显示为 `—` 表示当前模型不在官方价目表中(可用 `unknownModel: defaultModel` 改为按默认模型估算)。

## 修改后如何生效

profile 里的插件是 `file:` 依赖的**副本**(`nodeLinker: hoisted`),改动本目录的源码不会自动同步;而且 pnpm 只看依赖声明,直接 `pnpm add` 常常回一句 `Already up to date` 而不刷新副本。可靠的做法是先删再加:

```powershell
cd "$env:USERPROFILE\.dsh\profiles\desktop"
$pnpm = "$env:LOCALAPPDATA\Programs\DeepSeek Harness\resources\runtime\pnpm\bin\pnpm.mjs"
node $pnpm remove "@max/dsh-cost-meter"
node $pnpm add "file:<本目录的绝对路径>" --offline
```

改完核对一下副本与源码是否一致(`Get-FileHash`),然后在界面上**刷新一次页面**:运行中的页面持有的是已经求值过的旧模块,不刷新就不会执行新代码。若刷新后仍未变化,重启 DeepSeek Harness。

发布语义上的版本号要一并提高(`package.json` 的 `version`):客户端模块按版本区分代次,只改文件内容而不改版本,宿主不一定会推送新的模块代次。

## 配置

`cordis.patch.yml`:

```yaml
- insert:
    - id: cost-meter
      name: '@max/dsh-cost-meter'
      config:
        tier: auto                 # auto | peak | offPeak
        mode: ledger               # ledger | estimate
        defaultModel: deepseek-flash
        unknownModel: unpriced     # unpriced | defaultModel
        extraHolidays: []          # 额外按空闲(节假日)处理的日期 YYYY-MM-DD
        extraWorkdays: []          # 额外按工作日规则处理的日期(覆盖内置表)
        rates:                     # 可选:只写要覆盖的字段
          deepseek-flash:
            peak: { output: 8 }
```

| 字段 | 默认值 | 含义 |
| --- | --- | --- |
| `tier` | `auto` | 按北京时间自动判断高峰/空闲;也可固定为 `peak` 或 `offPeak`。 |
| `mode` | `ledger` | `ledger`:把每次观察到的用量增量按当时费率计价并累计到 localStorage(跨时段、跨模型更准,`seen` 只增不减,不会重复计费)。`estimate`:用当前时段单价直接乘会话总量。 |
| `defaultModel` | `deepseek-flash` | 会话还没有 `modelSelection` 记录时使用的模型。 |
| `unknownModel` | `unpriced` | 价目表里没有的模型:`unpriced` 显示 `—` 并不计价;`defaultModel` 用 `defaultModel` 的价格估算。 |
| `extraHolidays` | `[]` | 追加到内置节假日表的日期(`YYYY-MM-DD`),用于内置表还没覆盖的年份。 |
| `extraWorkdays` | `[]` | 强制按工作日规则处理的日期,用于修正内置表;优先级高于 `extraHolidays`。 |
| `rates` | 无 | 覆盖官方价目,按模型 id 合并。 |

## 实现

- **Host 半侧**(`index.js`)是空实现:插件没有 Host 状态,行存在的意义是让 `config` 有归属。
- **Client 半侧**(`client.js`)读取两个持久投影:
  - `tokenUsage` → `cacheReadTokens` / `uncachedInputTokens` / `cacheWriteTokens` / `outputTokens`;
  - `modelSelection` → 会话真正的路由模型。
- 注册到 `conversation.composer.dock`(`list` 插槽,session 作用域),自身实现样式与浮层,只依赖 `react`、`react-dom` 和 `--dsw-*` 主题变量。
- 文案走 Client locale 服务(命名空间 `@max/dsh-cost-meter`),语言服务缺失时退回内置词典。
- 时段判定用一张按年组织的节假日表(`STATUTORY_HOLIDAYS`)加两个集合:`holidays`(当天全天空闲)与 `workdays`(强制按工作日规则,用于纠错)。判定顺序是 workdays → holidays → 周六周日 → 两个时段窗口,全部在换算到北京时间后比较。

### 数据来源

- 价目:[DeepSeek API 文档 · 模型 & 价格](https://api-docs.deepseek.com/zh-cn/quick_start/pricing/)
- 节假日:[国务院办公厅关于2026年部分节假日安排的通知](https://www.gov.cn/zhengce/zhengceku/202511/content_7047091.htm)(国办发明电〔2025〕7号)

## 测试

```powershell
node --test test/pricing.test.mjs
```

测试直接加载 `client.js` 本体(用桩替换 `window.__ModuleLoader__`),覆盖价目表、时段判断、费用换算、账本增量与存储容错、格式化;另有三项**渲染回归测试**,用一个最小的 React 桩把真组件渲染出来,断言胶囊的金额文本、货币符号只出现一次、以及面板的明细行。

Install

dsh plugin --profile web add github:PennChong95/dsh-cost-meter

Profile: web

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