ChinRinhan/dsh-token-wall

dsh-token-wall

https://github.com/ChinRinhan/dsh-token-wall

未分類deepseekdeepseek-harnessdsh

dsh-token-wall

Token 用量看板插件,用于 DSH(DeepSeek Harness)。

按本机时区记录每次模型调用的 token 消耗,并把「攒了多少」做成看得见的方块墙。

  • 方块墙:每 10M tokens 填一格,100 格一页,累计只增不减
  • 桌宠:常驻角落里的小面板,本会话用量 + 上下文占用 + 全时累计块池,可拖动
  • 消耗分布:按工作区 / 模型 / 厂商三档切换
  • 设置页:区间汇总表,支持按天 / 周 / 月 / 渠道 / 模型 / 类型分组
  • 历史回填:从已有会话日志补齐历史,不是装上才开始记
  • 实时捕获:之后每次模型调用即时入账
包名是 dsh-token-wall(dsh-token-usage 已被另一个同类插件占用)。
插件内部的标识(路由前缀 /dsh-token-usage、存储目录、localStorage key)
都保持不变,所以升级不会丢历史数据。

安装

本插件以 Cordis bundle 形式发布,宿主是 DSH 的 Web profile。

⚠️ 本包尚未发布到 npm —— registry.npmjs.org/dsh-token-wall 目前返回 404。
所以当前唯一可用的路径是源码安装(方式一)。下面仍然保留了 npm 的写法,
等包正式发布后直接生效,不必再改文档。

方式一:从源码克隆(当前推荐)

# <profile> 通常是 ~/.dsh/profiles/<名字>
# Windows: %USERPROFILE%\.dsh\profiles\<名字>
cd ~/.dsh/profiles/<profile>/node_modules
git clone https://github.com/ChinRinhan/dsh-token-wall.git dsh-token-wall

想钉住某个版本就检出对应标签(列表见 Releases):

cd dsh-token-wall && git checkout v0.2.0

如果你要继续开发这个插件,用 link: 指向本地 clone 更方便(改完 client.js 走客户端 HMR 自动生效,不必重新安装):

"dsh-token-wall": "link:F:/path/to/dsh-token-wall"

方式二:从 npm 安装(待发布,暂不可用)

cd ~/.dsh/profiles/<profile>
npm install dsh-token-wall

方式三:用 DSH 的插件管理

在 DSH 会话里执行:

plugin_manager  install_bundle  target=dsh-token-wall
plugin_manager  set_bundle      target=dsh-token-usage  enabled=true

装完后:在 profile 里插入 bundle

无论用哪种方式,都要在 profile 的 cordis.patch.yml 里插入条目:

- insert:
    - id: dsh-token-usage          # ⚠️ 用这个 id,不是包名
      name: 'dsh-token-wall'
      config:
        keepDays: 400

⚠️ id 与 name 不同是有意的:id 是插件内部标识(决定路由前缀与存储目录), 必须保持 dsh-token-usage 才能沿用已有数据;name 才是包名。

验证装上

启用后宿主会注册四条路由。把 `` 换成你的 Web GUI 端口:

curl http://127.0.0.1:<port>/dsh-token-usage/today

返回 {"ok":true,"totals":{...},"allTime":{...},...} 就说明装好了。

界面上应该能看到三样东西:侧栏多出一个方块图标、右下角出现桌宠、设置页多出「Token 用量」一节。

首次启动会回填历史

backfillOnStart(默认开启)会扫描 $DSH_HOME/sessions 下的会话日志,把装上之前的用量补进来。

参考量级:本机 116 个会话、22 天、8,410 条记录,回填耗时数秒。

从旧目录名迁移

如果你之前是 clone 到 node_modules/dsh-token-usage 的,现在要换成 dsh-token-wall(包改名了,目录名跟着变):

cd ~/.dsh/profiles/<profile>
rm -rf node_modules/dsh-token-usage    # 旧目录(如果不是软链)
# 然后按「方式一」重新 clone,或等 npm 发布后走「方式二」

历史数据不需要迁移:存储路径由插件内部标识决定,与包名无关, 仍是 $DSH_HOME/token-usage/daily.json。

「从源码安装换成 npm 安装」这条路等包正式发布后才有意义,届时只需删掉旧目录再
npm install,数据同样不受影响。

界面

方块墙(主面板)

点侧栏的方块图标进入。外观见上方截图——主面板就是那一大片方块墙。

  • 每 10M tokens 一格:已填 / 正在填(按比例渐进)/ 空白,三态一眼分清
  • 每 10 格一道里程碑竖线(= 1 亿 tokens),首末行标出该行的量级,看颜色密度就能判断这一段是 2 亿还是 200 亿
  • 100 格一页(= 10 亿 tokens),自动停在第 N 页
  • 累计 / 今日 可切换:累计是只增不减的历史总量,今日是午夜归零的当天量
  • 页面下方是消耗分布与诊断信息

为什么是 10M:按真实数据量过,单轮对话中位 1.41M、p90 10.4M,典型活跃日 2–3 块、重度日 7–9 块。快慢都合适。

桌宠

常驻在窗口任意位置,也可以拖走。外观见上方截图的右下角。

  • 本会话:当前这个会话的用量。没有会话信息时显示 —(不显示 0)。
  • 进度条:当前这个 10M 方块的填充进度(blockWall().progress)——和池是

同一个量纲。快攒满(≥ 90%)时轻微呼吸。

  • 本轮:进行中的这一轮,实时在涨。harness 自带的「本轮用量」只在轮次**结束

后**才出现,这一点是它做不到的。

  • 池:全时累计块数,不随会话变。一个会话通常只有 0.2 块,跟随就会长期

显示「0 块」,失去意义。

  • 上下文:projectedTokens / contextWindow。这是唯一有后果的读数——

快满会被压缩。它是读数而不是进度条:60% 起转黄、85% 起转红。

  • 缓存:缓存读取 / 计费输入。这是成本的主要驱动(实测单个会话 119M 里

118.6M 是缓存读取),而它一直只藏在详情弹窗里。

  • 今日:今天的总量,给一个节奏参照。
  • 拖动:按住标题栏拖,指针移出窗口也继续跟手
  • 单击标题栏:折叠 / 展开。折叠态只留标题栏 + 大数字 + 池,且自适应——接近

压缩(≥ 80%)时显示上下文百分比,平时显示本会话量

  • 位置记忆:位置存在 localStorage,窗口缩放时自动钳制在可视范围内
  • 窄屏隐藏:≤768px 不显示(拖拽手势会和页面滚动打架)

动效很克制:进度条快攒满一块(≥ 90%)时轻微呼吸,攒到新的一块时池弹一下。系统开了「减少动态效果」时会全部关掉。

消耗分布

同一块区域,三个视角切换:

维度 · 回答的问题 工作区 · 我在哪个项目花得多 模型 · 我在用哪个模型花 厂商 · 我在给哪家公司送钱

「模型」视角会自动归并同一模型的不同写法。比如这四行其实是同一个模型:

deepseek-v4.1-flash             1.54B   ← 主名
workbuddy/deepseek-v4.1-flash   25.6M   ← 带渠道前缀
deepseek-ai/deepseek-v4.1-flash   52K   ← 另一种前缀
deepseek-v4.1-flash-free        23.1M   ← 带 free 后缀

归并后合成一行:1.62B · 4 个变体。

⚠️ 但不同代际不合并。deepseek-flash、deepseek-v4-flash、deepseek-v4.1-flash 是三个版本,合并会掩盖「还在用旧模型」这件事。

⚠️ 认不出厂商的模型归入「其他」,不猜。可以用配置里的 modelAliases 显式声明,见下。

当前在用的工作区 / 模型会高亮。

设置页

「Token 用量」一节包含:

  • 运行时开关(5 个,点完立即生效):桌宠、方块墙面板、输入框上方横幅,以及两个统计口径——含子会话、含辅助调用
  • 今日与累计卡片
  • 区间汇总表:按天 / 周 / 月 / 工作区 / 渠道 / 模型 / 渠道+模型 / 类型分组
  • 时长预设(近 7 天 / 30 天 / 90 天)+ 自定义起止日期
  • 过滤开关:含子会话、含辅助调用
  • 诊断区:已跟踪会话数、实时入账数、回填状态、存储位置

配置

在 profile 的 cordis.patch.yml 里覆盖,插件升级不会丢:

- id: dsh-token-usage              # 内部标识,不要改(决定路由前缀与存储目录)
  name: 'dsh-token-wall'           # 包名
  config:
    keepDays: 400              # 保留天数(落盘时淘汰更早的日键)
    includeSubagents: true     # 计入子代理 / 团队 / workflow 子会话
    includeAuxiliary: true     # 计入压缩等辅助调用
    statusBarEnabled: true     # 是否允许显示输入框上方的横幅
    statusBarRefreshMs: 1000   # 轮询间隔,最小 1000
    backfillOnStart: true      # 启动时回填历史

    # 可选:手动声明模型别名(认不出的模型可以在这里归类)
    modelAliases:
      dfmodel:
        vendor: deepseek
        model: deepseek-v4.1-flash

开关有两层,分别管什么

· 位置 · 生效方式 · 用途 config.statusBarEnabled · cordis.patch.yml · 重启 DSH · 部署期的硬开关 设置页五个开关 · $DSH_HOME/token-usage/prefs.json · 立即生效 · 日常调整

设置页那五个开关存在独立文件里,是因为改 Cordis config 要重启,而「我想把桌宠关掉」显然不该重启。